当前位置:网站首页>Use of observer mode and status mode in actual work
Use of observer mode and status mode in actual work
2022-06-30 06:06:00 【Tmi】
List of articles
One . Scenario requirements
Suppose the company now has a marketing campaign , User participation required , Complete a series of tasks , Finally, you can get some rewards in return .
Now you need to design and implement the task model . It is necessary to focus on the flow change of status and the notification after status change .
Two . Preliminary analysis , Code writing
Since it is a task , It must have its state , For example, initialization , complete , Overdue, etc . We can define an enumeration class for the task state .
Then everyone should do their own task , It must also have its own current task status , In other words, different user behaviors will trigger different task states . So we also define an enumeration class for the user's behavior state .
Then we mainly write the state change function here .
The code is as follows :
Two enumeration classes defined by
@AllArgsConstructor
@Getter
enum TaskStatus{
INIT(" initialization "),
ONGOING(" Have in hand "),
PAUSED(" Suspended "),
FINISHED(" Completed "),
EXPIRED(" Has expired ");
private final String message;
}
@AllArgsConstructor
@Getter
enum ActionType{
START(1," Start "),
STOP(2," Pause "),
ACHIEVE(3," complete "),
EXPIRED(4," Be overdue ");
private final int code;
private final String message;
}
Status change function
public class Task {
// Mission id
private Long taskId;
// The default status of tasks is initialization
private TaskStatus taskStatus=TaskStatus.INIT;
// External services on which the activity depends
private ActivityService activityService;
// Task manager
private TaskManager taskManager;
// Use conditional branches to update tasks
public void updateStatus(ActionType actionType){
// Task initialization status
if(taskStatus == TaskStatus.INIT ){
if(actionType == ActionType.START){
taskStatus = TaskStatus.ONGOING;
}
// The task is in progress
}else if(taskStatus == TaskStatus.ONGOING){
if(actionType == ActionType.ACHIEVE){
taskStatus = TaskStatus.FINISHED;
// Notify the external service after the task is completed , You can give rewards
activityService.notifyFinish();
taskManager.release(taskId);
}else if(actionType == ActionType.STOP){
taskStatus = TaskStatus.PAUSED;
}else if(actionType == ActionType.EXPIRED){
taskStatus = TaskStatus.EXPIRED;
}
// The mission is suspended
}else if(taskStatus == TaskStatus.PAUSED){
if(actionType == ActionType.START){
taskStatus = TaskStatus.ONGOING;
}else if(actionType == ActionType.EXPIRED){
taskStatus = TaskStatus.EXPIRED;
}
}
}
}
In the above implementation , There are two important functions
- Receive different behaviors , Then update the status of the current task
- When the task is done , Notify the activity to which the task belongs and the task manager
indeed , The above code implements the most basic functions , But there are still many problems .
- Not elegant enough , The above code uses many conditional statements , It's bloated , And it's not scalable , It's also very difficult to maintain , When there is a new status , We need to add if-else sentence , Against the principle of opening and closing .
- The task class is not cohesive enough , It perceives specific models of other domains or modules in the notification implementation , Such as specific external services and task managers , The coupling of such code is too high , Not conducive to expansion
So how to optimize it ?
- These two problems can be optimized through design patterns , First of all, the flow control of status can use The state pattern , secondly , The notification after the task is completed can use Observer mode
3、 ... and . Use design patterns for optimization
1. The state pattern


According to the definition of state mode :
We put TaskState The enumeration class is extended to multiple state classes , And have the ability to complete the circulation of the State
// Task state abstract interface
public interface TaskStatus {
// Default empty implementation , For subclasses to call or override
default void update(Task task,ActionType actionType) {
//do nothing
}
}
// Initial state of the task
class TaskInit implements TaskStatus {
@Override
public void update(Task task, ActionType actionType) {
if (actionType == ActionType.START) {
task.setTaskStatus(new TaskOngoing());
}
}
}
// Task progress status
class TaskOngoing implements TaskStatus {
private ActivityService activityService;
private TaskManager taskManager;
private Long taskId;
@Override
public void update(Task task, ActionType actionType) {
if (actionType == ActionType.ACHIEVE) {
task.setTaskStatus(new TaskFinished());
// notice
activityService.notifyFinish(taskId);
taskManager.release(taskId);
} else if (actionType == ActionType.STOP) {
task.setTaskStatus(new TaskPaused());
} else if (actionType == ActionType.EXPIRED) {
task.setTaskStatus(new TaskExpired());
}
}
}
// The task is suspended
class TaskPaused implements TaskStatus {
@Override
public void update(Task task, ActionType actionType) {
if (actionType == ActionType.START) {
task.setTaskStatus(new TaskOngoing());
} else if (actionType == ActionType.EXPIRED) {
task.setTaskStatus(new TaskExpired());
}
}
}
// Task completion status
class TaskFinished implements TaskStatus {
}
// Task expiration status
class TaskExpired implements TaskStatus {
}
@Data
public class Task {
public Task(Long taskId, TaskStatus taskStatus) {
this.taskId = taskId;
this.taskStatus = taskStatus;
}
private Long taskId;
// The task defaults to the initial state
private TaskStatus taskStatus=new TaskInit();
public void update(ActionType actionType){
taskStatus.update(this,actionType);
}
// Test call
public static void main(String[] args) {
Task task = new Task(2343L, new TaskOngoing());
task.update(ActionType.ACHIEVE);
}
}
@AllArgsConstructor
@Getter
enum ActionType{
START(1," Start "),
STOP(2," Pause "),
ACHIEVE(3," complete "),
EXPIRED(4," Be overdue ");
private final int code;
private final String message;
}
You can see , The coupling degree of task classes processed by state mode is reduced , Comply with opening and closing principle , The advantage of state mode is that it conforms to the principle of single responsibility , Clear state responsibilities , It's good for program expansion , But the cost of this design is that the number of state classes increases , Because the more complex the state flow logic is , The more actions you need to handle , The more conducive to the application of state mode . besides , The state class itself does not support the open close principle well enough , If the state flow logic changes frequently , Then it may be prudent to use .
Now? , According to Observer mode To optimize the notification when the task is completed :
2. Observer mode .


When we use observer mode , Notified , The object of action is the observer . Generate news , The subject of the notice is
So in this scenario , Notified Task Manager , External services are concrete observers , When the task status changes to end, you need to issue a notification , So the task status is the specific topic .
First design the abstract observer and the concrete observer
// Abstract observer
public interface Observer {
void response(Long taskId);
}
// External service observers
class ActivityServiceObserver implements Observer {
private ActivityService activityService;
@Override
public void response(Long taskId) {
activityService.notifyFinish(taskId);
}
};
// Task management observer
class TaskManagerObserver implements Observer {
private TaskManager taskManager;
@Override
public void response(Long taskId) {
taskManager.release(taskId);
}
};
Define abstract topics and concrete topics , Here, the task progress status is taken as a specific topic .
At the same time, when the initial status of the task flows , Define the desired observer , And it optimizes the notification in the task status into a general notification method .
// Abstract themes
abstract class Subject {
private List<Observer> observers = new ArrayList<>();
// Add observers
public void addObserver(Observer observer){
observers.add(observer);
}
// Delete observer
public void deleteObserver(Observer observer){
observers.remove(observer);
}
// Notify observer
public void notifyAll(Long taskId){
observers.forEach(observer -> observer.response(taskId));
}
}
/ Initial state of the task
class TaskInit implements TaskStatus {
@Override
public void update(Task task, ActionType actionType) {
if (actionType == ActionType.START) {
TaskOngoing taskOngoing = new TaskOngoing();
task.setTaskStatus(taskOngoing);
// During task initialization , Put the observers of the required notifications into the collection
taskOngoing.addObserver(new ActivityServiceObserver());
taskOngoing.addObserver(new TaskManagerObserver());
}
}
}
// Task progress status , It is also a specific theme
class TaskOngoing extends Subject implements TaskStatus {
private ActivityService activityService;
private TaskManager taskManager;
private Long taskId;
@Override
public void update(Task task, ActionType actionType) {
if (actionType == ActionType.ACHIEVE) {
task.setTaskStatus(new TaskFinished());
// Notification using observer mode
notifyAll(taskId);
} else if (actionType == ActionType.STOP) {
task.setTaskStatus(new TaskPaused());
} else if (actionType == ActionType.EXPIRED) {
task.setTaskStatus(new TaskExpired());
}
}
}
Through the observer model , Let the task state be loosely coupled with the notifier ( In fact, the observer model has not been completely decoupled , If you want to do further decoupling, you can consider learning and using publishing - A subscription model , I won't go into details here ).
thus , We have successfully designed high cohesion using state patterns 、 High scalability 、 The entire state machine implementation of a single responsibility task , And achieve loose coupling 、 Notification method of task status change in accordance with the principle of dependency inversion .
Actually , The only thing about design patterns is Find the change , Packaging changes

边栏推荐
猜你喜欢

Installation and initialization of MariaDB database

Today, Ali came out with 35K. It's really sandpaper that wiped my ass. it showed me my hand

Base64详解:玩转图片Base64编码

I have been working as a software testing engineer for 5 years, but I was replaced by an intern. How can I improve myself?

MySQL storage system

MySQL log management, data backup and recovery

MySQL 索引

我做功能测试这么多年的心得

JS prototype chain object function relationship

Application of redis client list in practice
随机推荐
VIM view file code
SparseArray
File operation io-part1
Mariadb数据库的安装与初始化
Feisheng: Based on the Chinese word breaker ik-2 ways to build custom hot word separators Showcase & pit arrangement Showtime
Variable parameters of go
MySQL advanced SQL statement
SHELL
UE4_ Editor development: highlight the UI making method according to the assets dragged by the mouse (1)
Codeforces C. Andrew and Stones
One sentence introduction to Trojan horse
Application of redis client list in practice
Summary of redis learning notes (I)
[exercise] basic practice letter graph of Blue Bridge Cup
At the beginning of 2022, people who are ready to change jobs should pay attention to
Learning automation ppt
Intelligent deodorizer embedded development
09- [istio] istio service entry
At the age of 32, I fell into a middle-aged crisis and finally quit naked...
MySQL日志管理、数据备份、恢复