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

边栏推荐
- [regular expression series] greedy and non greedy patterns
- Turn off automatic outlining in Visual Studio - turning off automatic outlining in Visual Studio
- InputStream转InputStreamSource
- [ansible series] fundamentals 02 module debug
- Verilog中case,casez,casex语句的用法
- 10-【istio】istio Sidecar
- 从零开发 stylelint规则(插件)
- 拼多多店铺搜索相关问题,为什么新品上架搜索不到
- Dynamic programming -- gliding wing of the strange thief Kidd
- Luogup2756 pilot pairing scheme problem (maximum flow)
猜你喜欢

Dynamic programming -- gliding wing of the strange thief Kidd

Cisco VXLAN配置

Balanced binary tree judgment of Li Kou 110 -- classic problems

重构之美:当多线程批处理任务挑起大梁 - 万能脚手架
![[ansible series] fundamentals -01](/img/b4/1f3284338c75acb5259849a45bbfbe.jpg)
[ansible series] fundamentals -01

电脑查看WiFi使用密码

The average salary of software testing in 2022 has been released. Have you been averaged?

MySQL advanced SQL statement

Mysql database learning notes - foreign keys, table connections, subqueries, and indexes for MySQL multi table queries

Finally someone can make the server so straightforward
随机推荐
CompletableFuture从了解到精通,你想知道的这里都有
RSA and AES
Es6数组
requests. The difference between session () sending requests and using requests to send requests directly
InputStream to inputstreamsource
从底层结构开始学习FPGA----RAM IP核及关键参数介绍
luoguP2756 飞行员配对方案问题(最大流)
Mysql database learning notes - foreign keys, table connections, subqueries, and indexes for MySQL multi table queries
Share problems solved
Shenzhou ares tx6 boot logo modification tutorial
MySQL log management, data backup and recovery
ES6扩展运算符(...)
IP TCP UDP network encryption suite format
Switch to software testing and report to the training class for 3 months. It's a high paying job. Is it reliable?
One sentence introduction to Trojan horse
股票在网上开户安全吗?在网上能不能开户炒股呢?
Mariadb数据库的安装与初始化
Go common judgments
Attempt to redefine 'timeout' at line 2 solution
Implementation of property management system with ssm+ wechat applet