状态模式(State Pattern)又称状态机模式,是允许对象在内部状态发生改变时改变他的的行为,类的行为由状态决定,不同的状态有着不同的行为,对象看起来好像修改了它的类。属于行为型模式。

一般涉及到电商订单相关的,会采用状态模式来设计,不同的订单状态,响应的都有不同的操作。

适用场景

1) 行为随状态改变而改变的场景
2) 一个操作中含有庞大的多分支结构,并且这些分支取决于对象的状态

主要设计结构图

代码演示

状态抽象对象

public abstract class State {private AppContext context;public void setContext(AppContext context) {this.context = context;}public AppContext getContext() {return context;}abstract void favourite();abstract void updatePwd();
}

具体不同状态

public class GuestState extends State {@Overridevoid favourite() {forwardToLoginPage();this.getContext().favourite();}@Overridevoid updatePwd() {forwardToLoginPage();this.getContext().updatePwd();}private void forwardToLoginPage() {System.out.println("跳转到登陆页面");this.getContext().setState(AppContext.STATE_LOGIN);}
}
public class LoginState extends State {@Overridevoid favourite() {System.out.println("登陆成功,跳转到首页");System.out.println("收藏成功!");}@Overridevoid updatePwd() {System.out.println("修改安全信息,需要再次验证您的身份!");this.getContext().setState(AppContext.STATE_REAUTH);this.getContext().updatePwd();}
}
public class ReauthState extends State {@Overridevoid favourite() {System.out.println("收藏成功!");}@Overridevoid updatePwd() {System.out.println("密码修改成功!");}
}

上下文对象

public class AppContext {protected static final State STATE_GUEST = new GuestState();protected static final State STATE_LOGIN = new LoginState();protected static final State STATE_REAUTH = new ReauthState();private State currentSate = STATE_GUEST;{STATE_GUEST.setContext(this);STATE_LOGIN.setContext(this);STATE_REAUTH.setContext(this);}public void setState(State state) {this.currentSate = state;}public void favourite() {this.currentSate.favourite();}public void updatePwd() {this.currentSate.updatePwd();}
}

测试类

public class Test {public static void main(String[] args) {AppContext context = new AppContext();context.favourite();context.updatePwd();}
}

执行结果

跳转到登陆页面
登陆成功,跳转到首页
收藏成功!
修改安全信息,需要再次验证您的身份!
密码修改成功!

Spring中状态模式的应用:StateMachine状态机

使用Spring状态机实现订单业务

pom依赖导入

<dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-core</artifactId><version>2.0.1.RELEASE</version>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId><version>2.6.8</version>
</dependency>

订单类

public class Order {private int id;private OrderStatus status;public void setStatus(OrderStatus status) {this.status = status;}public OrderStatus getStatus() {return status;}public void setId(int id) {this.id = id;}public int getId() {return id;}@Overridepublic String toString() {return "订单号:" + id + ", 订单状态:" + status;}
}

订单状态

public enum OrderStatus {// 待支付,待发货,待收货,订单结束WAIT_PAYMENT, WAIT_DELIVER, WAIT_RECEIVE, FINISH;
}

订单状态对应的改变事件

public enum OrderStatusChangeEvent {// 支付,发货,确认收货PAYED, DELIVERY, RECEIVED;
}

订单状态机配置

@Configuration
@EnableStateMachine(name = "orderStateMachine")
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderStatus, OrderStatusChangeEvent> {/*** 配置状态* @param states* @throws Exception*/public void configure(StateMachineStateConfigurer<OrderStatus, OrderStatusChangeEvent> states) throws Exception {states.withStates().initial(OrderStatus.WAIT_PAYMENT).states(EnumSet.allOf(OrderStatus.class));}/*** 配置状态转换事件关系* @param transitions* @throws Exception*/public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderStatusChangeEvent> transitions) throws Exception {transitions.withExternal().source(OrderStatus.WAIT_PAYMENT).target(OrderStatus.WAIT_DELIVER).event(OrderStatusChangeEvent.PAYED).and().withExternal().source(OrderStatus.WAIT_DELIVER).target(OrderStatus.WAIT_RECEIVE).event(OrderStatusChangeEvent.DELIVERY).and().withExternal().source(OrderStatus.WAIT_RECEIVE).target(OrderStatus.FINISH).event(OrderStatusChangeEvent.RECEIVED);}/*** 持久化配置* 实际使用中,可以配合redis等,进行持久化操作* @return*/@Beanpublic DefaultStateMachinePersister persister(){return new DefaultStateMachinePersister<>(new StateMachinePersist<Object, Object, Order>() {@Overridepublic void write(StateMachineContext<Object, Object> context, Order order) throws Exception {//此处可以对订单状态进行持久化操作}@Overridepublic StateMachineContext<Object, Object> read(Order order) throws Exception {//此处直接获取order中的状态,其实并没有进行持久化读取操作return new DefaultStateMachineContext(order.getStatus(), null, null, null);}});}
}

订单状态监听,并根据状态机配置做出相应的事件

@Component("orderStateListener")
@WithStateMachine(name = "orderStateMachine")
public class OrderStateListenerImpl{@OnTransition(source = "WAIT_PAYMENT", target = "WAIT_DELIVER")public boolean payTransition(Message<OrderStatusChangeEvent> message) {Order order = (Order) message.getHeaders().get("order");order.setStatus(OrderStatus.WAIT_DELIVER);System.out.println("支付,状态机反馈信息:" + message.getHeaders().toString());return true;}@OnTransition(source = "WAIT_DELIVER", target = "WAIT_RECEIVE")public boolean deliverTransition(Message<OrderStatusChangeEvent> message) {Order order = (Order) message.getHeaders().get("order");order.setStatus(OrderStatus.WAIT_RECEIVE);System.out.println("发货,状态机反馈信息:" + message.getHeaders().toString());return true;}@OnTransition(source = "WAIT_RECEIVE", target = "FINISH")public boolean receiveTransition(Message<OrderStatusChangeEvent> message){Order order = (Order) message.getHeaders().get("order");order.setStatus(OrderStatus.FINISH);System.out.println("收货,状态机反馈信息:" + message.getHeaders().toString());return true;}
}

订单服务接口

public interface IOrderService {//创建新订单Order create();//发起支付Order pay(int id);//订单发货Order deliver(int id);//订单收货Order receive(int id);//获取所有订单信息Map<Integer, Order> getOrders();
}

订单服务实现类

@Service("orderService")
public class OrderServiceImpl implements IOrderService {@Autowiredprivate StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;@Autowiredprivate StateMachinePersister<OrderStatus, OrderStatusChangeEvent, Order> persister;private int id = 1;private Map<Integer, Order> orders = new HashMap<>();public Order create() {Order order = new Order();order.setStatus(OrderStatus.WAIT_PAYMENT);order.setId(id++);orders.put(order.getId(), order);return order;}public Order pay(int id) {Order order = orders.get(id);System.out.println("线程名称:" + Thread.currentThread().getName() + " 尝试支付,订单号:" + id);Message message = MessageBuilder.withPayload(OrderStatusChangeEvent.PAYED).setHeader("order", order).build();if (!sendEvent(message, order)) {System.out.println("线程名称:" + Thread.currentThread().getName() + " 支付失败, 状态异常,订单号:" + id);}return orders.get(id);}public Order deliver(int id) {Order order = orders.get(id);System.out.println("线程名称:" + Thread.currentThread().getName() + " 尝试发货,订单号:" + id);if (!sendEvent(MessageBuilder.withPayload(OrderStatusChangeEvent.DELIVERY).setHeader("order", order).build(), orders.get(id))) {System.out.println("线程名称:" + Thread.currentThread().getName() + " 发货失败,状态异常,订单号:" + id);}return orders.get(id);}public Order receive(int id) {Order order = orders.get(id);System.out.println("线程名称:" + Thread.currentThread().getName() + " 尝试收货,订单号:" + id);if (!sendEvent(MessageBuilder.withPayload(OrderStatusChangeEvent.RECEIVED).setHeader("order", order).build(), orders.get(id))) {System.out.println("线程名称:" + Thread.currentThread().getName() + " 收货失败,状态异常,订单号:" + id);}return orders.get(id);}public Map<Integer, Order> getOrders() {return orders;}/*** 发送订单状态转换事件** @param message* @param order* @return*/private synchronized boolean sendEvent(Message<OrderStatusChangeEvent> message, Order order) {boolean result = false;try {orderStateMachine.start();//尝试恢复状态机状态persister.restore(orderStateMachine, order);//添加延迟用于线程安全测试Thread.sleep(1000);result = orderStateMachine.sendEvent(message);//持久化状态机状态persister.persist(orderStateMachine, order);} catch (Exception e) {e.printStackTrace();} finally {orderStateMachine.stop();}return result;}
}

打印结果

线程名称:主线程 尝试支付,订单号:1
支付,状态机反馈信息:{order=订单号:1, 订单状态:WAIT_DELIVER, id=ee9f1da9-c0f0-0305-01ca-41cba1b591af, timestamp=1654393420238}
线程名称:主线程 尝试支付,订单号:2
线程名称:客户线程 尝试发货,订单号:1
支付,状态机反馈信息:{order=订单号:2, 订单状态:WAIT_DELIVER, id=0bc9a66f-dc74-4490-26f7-82f656a36c83, timestamp=1654393421262}
线程名称:主线程 尝试发货,订单号:2
发货,状态机反馈信息:{order=订单号:2, 订单状态:WAIT_RECEIVE, id=e8e48269-b184-f238-aac2-ddcc48cc59c5, timestamp=1654393422267}
线程名称:主线程 尝试收货,订单号:2
发货,状态机反馈信息:{order=订单号:1, 订单状态:WAIT_RECEIVE, id=b4753603-a89e-7599-ac38-50f118aa048c, timestamp=1654393421263}
线程名称:客户线程 尝试收货,订单号:1
收货,状态机反馈信息:{order=订单号:2, 订单状态:FINISH, id=bd30bf3c-75a6-839a-9751-02bada949dc8, timestamp=1654393423269}
全部订单状态:{1=订单号:1, 订单状态:WAIT_RECEIVE, 2=订单号:2, 订单状态:FINISH}
收货,状态机反馈信息:{order=订单号:1, 订单状态:FINISH, id=dad2da8e-2e5e-0786-7b20-fcbf713ab5ea, timestamp=1654393424272}

设计模式——状态模式(State Pattern)相关推荐

  1. php 状态模式,PHP设计模式(十九)—状态模式 (State Pattern)

    状态模式 (State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类.其别名为状态对象(Objects for States) (一)为什么需要状态模式 ...

  2. 设计模式(十二):通过ATM取款机来认识“状态模式”(State Pattern)

    说到状态模式,如果你看过之前发布的重构系列的文章中的<代码重构(六):代码重构完整案例>这篇博客的话,那么你应该对"状态模式"并不陌生,因为我们之前使用到了状态模式进行 ...

  3. 极速理解设计模式系列:22.状态模式(State Pattern)

    四个角色:抽象状态类(State).具体状态类(ConcreateState).情景类(Context).客户端(Client) 抽象状态类(State):提供一个与情景类有关的State行为. 具体 ...

  4. 趣谈设计模式 | 状态模式(State):如何实现游戏中的状态切换?

    文章目录 案例:马里奥积分竞赛 有限状态机 分支逻辑法 查表法 状态模式 状态模式与策略模式 总结 完整代码与文档 案例:马里奥积分竞赛 喜欢马里奥的小伙伴们都应该知道,前不久马里奥为了庆祝35周年, ...

  5. C++设计模式--状态模式(state)

    概述 前面文章介绍了代理模式(在这里),代理模式和状态模式都提供一个代理类,从结构上看,可以认为代理模式只是状态模式的一个特例,不同之处在于,代理模式控制对其实现类的访问,而状态模式动态地改变其实现类 ...

  6. 状态模式(State Pattern)

    状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类 考虑如下场景,自动售票机: 每一个方格表示自动售票机的一种状态,每一个箭头线表示自动售票机由一个状态转换到另一个状态所需要的 ...

  7. 41状态模式(State Pattern)

    对象状态影响对象行为:     对象拥有不同的状态,往往会行使不同的行为...                     动机:     在软件构建过程中,某些对象的状态如果改变以及其行为也会随之而发生 ...

  8. C++设计模式——状态模式(state pattern)

    一.原理讲解 别名状态对象(object for state). 1.1意图 允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改了它的类. 1.2应用场景 一个对象的行为取决于它的状态,并 ...

  9. 【转】设计模式 ( 十七) 状态模式State(对象行为型)

    设计模式 ( 十七) 状态模式State(对象行为型) 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ...

  10. Python设计模式-状态模式

    Python设计模式-状态模式 代码基于3.5.2,代码如下; #coding:utf-8 #状态模式class state():def writeProgram(self,work):raise N ...

最新文章

  1. 小模型实现大一统!FBNetV5一举包揽CV任务3个SOTA
  2. 剥开比原看代码08:比原的Dashboard是怎么做出来的?
  3. 好好学python·基本数据类型
  4. 我看Chrome超越IE的意义
  5. 腾讯云上午突发故障 称运营商光缆中断所致
  6. Python 百度面试题
  7. winScp中文乱码设置
  8. 一个公网ip多少钱_一个丛书书号多少钱
  9. Stable Region Correspondences Between Non-Isometric Shapes
  10. 大佬是如何实现本地通讯的?
  11. BZOJ3561 DZY Loves Math VI
  12. OpenCV在图片和视频中的人脸检测
  13. 从零开始搭建自己的网站四:博客网站模板下载
  14. aws----文件存储efs的全面了解
  15. Unity接入心知天气,获取当前城市天气状况
  16. Sping aop XML与注解方式
  17. kali中steghide命令工具教程;7z命令详解;kali中base64命令详解
  18. ami免刷bios 开启bios设置
  19. Linux文件类型与扩展名
  20. 爬虫做js逆向分析的思路

热门文章

  1. 40个创意的IPhone壁纸大集合,做应用程序必备
  2. 关闭显卡快捷键 CTRL+ALT+方向键
  3. 黑客利用数百万路由器的新身份验证绕过漏洞
  4. python面向对象小项目_python之面向对象
  5. 进入瓶颈期的格力,多元化能助其解围吗?
  6. 仿真器+编程器+实验板与开发板的区别
  7. 记录--NPM卸载命令
  8. 新文联播第8期 | tDCS可改善强迫症症状,调节皮层抑制
  9. 人脸识别——脸部属性辅助(得分层)
  10. 夜光 带你走进 Java基础编程实战(十六 Applet编程)