状态机——枚举实现简单状态机
枚举实现简单状态机1、业务场景订单状态流转2、代码实现3、上下文对象Context4、测试运行5、总结在 Java 中使用枚举Enum来实现状态机State Machine是一种非常优雅且高效的做法。Java 的枚举不仅是一个常量的集合它本质上是一个闭合的类可以拥有属性、方法甚至可以实现接口。最经典、最符合面向对象设计原则的实现方式是将状态的行为抽象成方法并在每个枚举常量中分别实现它状态模式。1、业务场景订单状态流转我们以一个简单的“订单系统”为例订单有三个状态待付款 (CREATED)待发货 (PAID)已收货 (DELIVERED)触发状态流转的动作事件有pay()付款ship()发货2、代码实现通过在枚举中定义抽象方法每个状态都可以决定自己在收到某个事件时该如何跳转。publicenumOrderState{// 1. 待付款状态CREATED{OverridepublicOrderStatepay(){System.out.println(订单付款成功 - 准备发货);returnPAID;// 流转到下一个状态}OverridepublicOrderStateship(){System.out.println(错误订单尚未付款不能发货);returnthis;// 保持原状态}},// 2. 待发货状态PAID{OverridepublicOrderStatepay(){System.out.println(提示订单已付款请勿重复支付。);returnthis;}OverridepublicOrderStateship(){System.out.println(订单发货成功 - 商品运输中);returnDELIVERED;// 流转到下一个状态}},// 3. 已收货状态终态DELIVERED{OverridepublicOrderStatepay(){System.out.println(错误订单已结束无法付款。);returnthis;}OverridepublicOrderStateship(){System.out.println(错误订单已结束无法重复发货。);returnthis;}};// 抽象出状态机能接收的事件动作publicabstractOrderStatepay();publicabstractOrderStateship();}3、上下文对象Context在实际业务中我们通常会有一个订单类Order它持有了当前的状态并对外暴露统一的调用接口。publicclassOrderContext{privateStringorderId;privateOrderStatestate;// 持有当前状态publicOrderContext(StringorderId){this.orderIdorderId;this.stateOrderState.CREATED;// 初始状态为待付款}// 触发付款动作publicvoidpayAction(){// 将状态变更的控制权交给状态枚举本身this.statethis.state.pay();}// 触发发货动作publicvoidshipAction(){this.statethis.state.ship();}publicOrderStategetState(){returnstate;}}4、测试运行publicclassStateMachineTest{publicstaticvoidmain(String[]args){OrderContextordernewOrderContext(10001);System.out.println(当前状态order.getState());// CREATED// 1. 尝试直接发货非法操作order.shipAction();// 输出: 错误订单尚未付款不能发货// 2. 正常付款order.payAction();// 输出: 订单付款成功 - 准备发货System.out.println(当前状态order.getState());// PAID// 3. 正常发货order.shipAction();// 输出: 订单发货成功 - 商品运输中System.out.println(当前状态order.getState());// DELIVERED}}当前状态CREATED 错误订单尚未付款不能发货 订单付款成功 - 准备发货 当前状态PAID 订单发货成功 - 商品运输中 当前状态DELIVERED5、总结优点避免了密集的 if-else 或 switch-case传统的做法通常是在一个方法里写一大堆 if (status CREATED) { … } else if …。使用枚举将行为内聚到各个状态内部代码极其清晰。线程安全与单例保证Java 的枚举实例底层是高级单例JVM 保证了它们的线程安全和全局唯一性。强类型校验编译器会强制要求你流转后的状态必须也是 OrderState 之一不会出现拼写错误或传入非法状态码的情况。适用场景这种流转逻辑相对固定、状态数量不是特别庞大比如10个以内的本地轻量级状态机。如果业务极其复杂且带有大量分布式事务如跨服务流转则可以考虑官方的 Spring StateMachine 或阿里开源的 Cola StateMachine。