当前位置:网站首页>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

边栏推荐
- Variable parameters of go
- MySQL 索引
- MySQL advanced SQL statement
- [OSPF] comparison between rip and OSPF
- 从零开发 stylelint规则(插件)
- 云服务器部署 Web 项目
- Decompilation normal decompilation problems. Solve them yourself
- Shenzhou ares tx6 boot logo modification tutorial
- Related applications of priority queue
- Prototype and prototype chain in JS
猜你喜欢

Tornado frame foundation

MySQL index

MySQL advanced (Advanced SQL statement)

At the beginning of 2022, people who are ready to change jobs should pay attention to

JS prototype chain object function relationship

Leetcode search insert location

Switch to software testing and report to the training class for 3 months. It's a high paying job. Is it reliable?

重构之美:当多线程批处理任务挑起大梁 - 万能脚手架

从底层结构开始学习FPGA----RAM IP核及关键参数介绍

MySQL storage system
随机推荐
[ansible series] fundamentals -01
Common address collection
[GPU] basic operation
880. 索引处的解码字符串
云服务器部署 Web 项目
PC viewing WiFi password
Summary of 2 billion redis data migration
Related applications of priority queue
反编译正常回编译出现问题自己解决办法
股票在网上开户安全吗?在网上能不能开户炒股呢?
CompletableFuture从了解到精通,你想知道的这里都有
二十四、输入输出设备模型(串口/键盘/磁盘/打印机/总线/中断控制器/DMA和GPU)
Problems related to pinduoduo store search, why can't new products be found on the shelves
Go common judgments
Master slave synchronization of MySQL database to realize read-write separation
网络基础知识
Mysql database learning notes - foreign keys, table connections, subqueries, and indexes for MySQL multi table queries
General contents of learning reinforcement learning
583. 两个字符串的删除操作-动态规划
Navigate back to fragmentpageradapter - & gt; Fragment is empty - navigating back to fragmentpageradapter - & gt; fragments are empty