设计模式之状态模式

news/2024/4/27 22:09:15

经典案例:任务状态流转的过程

private String state = StateEnum.INIT.getStateValue();
public String update(ActionEnum actionEnum){if (StateEnum.INIT.getStateValue().equals(state)) {//初始化 -> 进行中if (ActionEnum.START == actionEnum) {state = StateEnum.ONGOING.getStateValue();}} else if (StateEnum.ONGOING.getStateValue().equals(state)) {//进行中 -> 已完成   进行中 -> 暂停中   进行中 -> 已过期if (actionEnum == ActionEnum.ACHIEVE) {state = StateEnum.FINISHED.getStateValue();}else if (actionEnum == ActionEnum.STOP){state = StateEnum.PAUSED.getStateValue();}else if (actionEnum == ActionEnum.EXPIRE){state = StateEnum.EXPIRED.getStateValue();}}else if (StateEnum.PAUSED.getStateValue().equals(state)) {//暂停中 -> 进行中   暂停中 -> 已过期if (actionEnum == ActionEnum.START) {state = StateEnum.ONGOING.getStateValue();}else if (actionEnum == ActionEnum.EXPIRE){state = StateEnum.EXPIRED.getStateValue();}}else if (StateEnum.FINISHED.getStateValue().equals(state)) {}else if (StateEnum.EXPIRED.getStateValue().equals(state)) {}return state;
}

        不难看出,状态流转的过程使用了大量的if-else做判断,条件复杂或者状态太多时,条件判断语句会过于臃肿,可读性差,且不具备扩展性,维护难度也大。且增加新的状态时要添加新的if-else语句,这违背了开闭原则,不利于程序的扩展。那么可以使用状态模式解决以上的问题,参考美团:设计模式二三事。

        

状态模式:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。状态模式包含以下主要角色:

  • 环境类(Context)角色:也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。

  • 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。

  • 具体状态(Concrete State)角色:实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。

/*** @author maoyouhua* @time 2024/3/19* @jdkversion jdk21* *     枚举类*/
@AllArgsConstructor
@Getter
public enum ActionEnum {START( "开始"),STOP("暂停"),ACHIEVE("完成"),EXPIRE("过期");private final String actionValue;
}
@AllArgsConstructor
@Getter
public enum StateEnum {INIT("初始化"),ONGOING( "进行中"),PAUSED("暂停中"),FINISHED("已完成"),EXPIRED("已过期");private final String stateValue;public String getStateValue() {return stateValue;}
}
/*** @author maoyouhua* @time 2024/3/19* @jdkversion jdk21*  *      抽象状态*/
public abstract interface State {void update(TaskService taskService, ActionEnum actionEnum);String getCurrentState();
}
public abstract class AbstractState implements State {}
/*** @author maoyouhua* @time 2024/3/19* @jdkversion jdk21* *      具体状态*      此处有spring循环依赖的问题 需要加配置 spring.main.allow-circular-references=true*/
@Component
public class InitState extends AbstractState {@Autowiredprivate OnGoingState onGoingState;public static final String stateValue = StateEnum.INIT.getStateValue();@Overridepublic void update(TaskService taskService, ActionEnum actionEnum) {//初始化 -> 进行中if (actionEnum == ActionEnum.START) {taskService.setTaskState(onGoingState);}}@Overridepublic String getCurrentState() {return stateValue;}
}
@Component
public class OnGoingState extends AbstractState {@Autowiredprivate FinishedState finishedState;@Autowiredprivate ExpiredState expiredState;@Autowiredprivate PausedState pausedState;public static final String stateValue = StateEnum.ONGOING.getStateValue();@Overridepublic void update(TaskService taskService, ActionEnum actionEnum) {//进行中 -> 已完成   进行中 -> 暂停中   进行中 -> 已过期if (actionEnum == ActionEnum.ACHIEVE) {taskService.setTaskState(finishedState);}else if (actionEnum == ActionEnum.STOP){taskService.setTaskState(pausedState);}else if (actionEnum == ActionEnum.EXPIRE){taskService.setTaskState(expiredState);}}@Overridepublic String getCurrentState() {return stateValue;}
}
@Component
public class PausedState extends AbstractState {@Autowiredprivate OnGoingState onGoingState;@Autowiredprivate ExpiredState expiredState;public static final String stateValue = StateEnum.PAUSED.getStateValue();@Overridepublic void update(TaskService taskService, ActionEnum actionEnum) {// 暂停中 -> 进行中      暂停中 -> 已过期if (actionEnum == ActionEnum.START) {taskService.setTaskState(onGoingState);}else if (actionEnum == ActionEnum.EXPIRE){taskService.setTaskState(expiredState);}}@Overridepublic String getCurrentState() {return stateValue;}
}
@Component
public class FinishedState extends AbstractState {public static final String stateValue = StateEnum.FINISHED.getStateValue();@Overridepublic void update(TaskService taskService, ActionEnum actionEnum) {}@Overridepublic String getCurrentState() {return stateValue;}
}
@Component
public class ExpiredState extends AbstractState {public static final String stateValue = StateEnum.EXPIRED.getStateValue();@Overridepublic void update(TaskService taskService, ActionEnum actionEnum) {}@Overridepublic String getCurrentState() {return stateValue;}
}
/*** @author maoyouhua* @time 2024/3/19* @jdkversion jdk21**          多线程不安全*/
public interface TaskService {void updateState(ActionEnum actionEnum);State getTaskState();void setTaskState(State state);
}
@Component
public class TaskServiceImpl implements TaskService {private State state;@Autowiredpublic TaskServiceImpl(InitState initState) {this.state = initState;}@Overridepublic void updateState(ActionEnum actionEnum){state.update(this,actionEnum);}@Overridepublic State getTaskState() {return state;}@Overridepublic void setTaskState(State state) {this.state = state;}}
/*** @author maoyouhua* @time 2024/3/19* @jdkversion jdk21*/
@RestController
@RequestMapping("/task")
public class TaskController {private String state = StateEnum.INIT.getStateValue();@Autowiredprivate TaskService taskService;@RequestMapping("/test")public String test(){return "任务测试";}/**** @param actionEnum  START、STOP、ACHIEVE、EXPIRE* @return*/@RequestMapping("/update")public String update(ActionEnum actionEnum){if (StateEnum.INIT.getStateValue().equals(state)) {//初始化 -> 进行中if (ActionEnum.START == actionEnum) {state = StateEnum.ONGOING.getStateValue();}} else if (StateEnum.ONGOING.getStateValue().equals(state)) {//进行中 -> 已完成   进行中 -> 暂停中   进行中 -> 已过期if (actionEnum == ActionEnum.ACHIEVE) {state = StateEnum.FINISHED.getStateValue();}else if (actionEnum == ActionEnum.STOP){state = StateEnum.PAUSED.getStateValue();}else if (actionEnum == ActionEnum.EXPIRE){state = StateEnum.EXPIRED.getStateValue();}}else if (StateEnum.PAUSED.getStateValue().equals(state)) {//暂停中 -> 进行中   暂停中 -> 已过期if (actionEnum == ActionEnum.START) {state = StateEnum.ONGOING.getStateValue();}else if (actionEnum == ActionEnum.EXPIRE){state = StateEnum.EXPIRED.getStateValue();}}else if (StateEnum.FINISHED.getStateValue().equals(state)) {}else if (StateEnum.EXPIRED.getStateValue().equals(state)) {}return state;}@RequestMapping("/updateByStateMode")public String updateByStateMode(ActionEnum actionEnum){taskService.updateState(actionEnum);return taskService.getTaskState().getCurrentState();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.cpky.cn/p/10931.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

在 Linux/Ubuntu/Debian 上安装 SQL Server 2019

Microsoft 为 Linux 发行版(包括 Ubuntu)提供 SQL Server。 以下是有关如何执行此操作的基本指南: 注册 Microsoft Ubuntu 存储库并添加公共存储库 GPG 密钥: sudo wget -qO- https://packages.microsoft.com/keys/microsoft.as…

【GO全栈掌握入门】

GO语言全栈学习咯 ~ 1. GO 语言简介2.语言特性3.哪些公司使用GO语言?3. 安装GO开发环境4. 学习说明:5. GO结构篇5.1 工作空间5.2 导入包5.3 组织结构5.4 依赖管理 6. GO骨肉篇7.GO工具篇 1. GO 语言简介 起源于2007年,GO语言之年轻如你所见&…

【LabVIEW FPGA入门】使用FPGA实现串行同步接口(SSI)

SSI(串行同步接口)是连接绝对位置传感器和控制器的广泛应用的串行接口。SSI利用控制器发出一个时钟脉冲序列,初始化传感器的门限输出。 传感器不断更新位置数据,并传送到移位寄存器中。在每一个时钟脉冲序列之间&#xff…

Blender小:图片转mesh,并展UV

其实就这么一个插件:Image2Mesh https://github.com/kedepot/i2m-std blender加载完图片之后点这个就行 到了这一步还不行如果直接放到unity中使用的话,添加材质和贴图之后每一个小块都是独立的区域来展示贴图,所以需要展UV

【C++练级之路】【Lv.15】AVL树(双子旋转,领略绝对平衡之美)

快乐的流畅:个人主页 个人专栏:《C语言》《数据结构世界》《进击的C》 远方有一堆篝火,在为久候之人燃烧! 文章目录 引言一、AVL树的概念二、AVL树的模拟实现2.1 结点2.2 成员变量2.3 插入2.4 旋转2.4.1 左单旋2.4.2 右单旋2.4.3 …

CSDN个人简介优化 html font属性

CSDN个人简介优化 html font属性 个人简介个人简介优化字体21种样式选择字体大小设置4号字体 字体颜色设计渐变色&#xff08;可惜不能显示&#xff09; 字体加粗设置 <b>标签 个人简介 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光…