首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

状态模式:有限状态机在电商订单系统中的设计与实现

  • 25-04-18 16:21
  • 3065
  • 11929
juejin.cn

状态模式:有限状态机在电商订单系统中的设计与实现

一、模式核心:用状态切换驱动行为变化

在电商订单系统中,订单状态会随着用户操作动态变化:「已创建」的订单支付后变为「已支付」,发货后变为「已发货」,不同状态下的操作权限和业务逻辑差异巨大。传统方式通过大量if-else判断状态,导致代码臃肿且难以维护。状态模式(State Pattern) 通过将状态封装为独立类,使对象在不同状态下自动切换行为,核心解决:

  • 状态驱动行为:不同状态对应不同操作逻辑,避免海量条件判断
  • 状态转换可控:集中管理状态迁移规则,确保状态变化符合业务流程

核心思想与 UML 类图

img

二、核心实现:构建可扩展的订单状态机

1. 定义状态接口(封装状态相关操作)

java
代码解读
复制代码
public interface OrderState { // 支付操作:不同状态下支付逻辑不同 void pay(OrderContext context); // 发货操作:仅特定状态允许发货 void deliver(OrderContext context); // 取消操作:不同状态下取消流程不同 void cancel(OrderContext context); }

2. 实现具体状态类(封装各状态的行为)

已创建状态(允许支付和取消)
java
代码解读
复制代码
public class CreatedState implements OrderState { @Override public void pay(OrderContext context) { System.out.println("订单创建状态:执行支付流程..."); context.setCurrentState(new PaidState()); // 切换到已支付状态 System.out.println("状态变更:已创建 → 已支付"); } @Override public void deliver(OrderContext context) { throw new IllegalStateException("错误:未支付订单不能发货"); } @Override public void cancel(OrderContext context) { System.out.println("订单创建状态:执行取消流程(无需扣款)"); context.setCurrentState(new CanceledState()); // 切换到已取消状态 } }
已支付状态(允许发货和取消)
java
代码解读
复制代码
public class PaidState implements OrderState { @Override public void pay(OrderContext context) { throw new IllegalStateException("错误:订单已支付,请勿重复支付"); } @Override public void deliver(OrderContext context) { System.out.println("订单支付状态:执行发货流程..."); context.setCurrentState(new DeliveredState()); // 切换到已发货状态 System.out.println("状态变更:已支付 → 已发货"); } @Override public void cancel(OrderContext context) { System.out.println("订单支付状态:执行取消流程(需退款)"); context.setCurrentState(new CanceledState()); } }

3. 上下文类(管理状态切换与状态相关数据)

java
代码解读
复制代码
public class OrderContext { private OrderState currentState; private final String orderId; public OrderContext(String orderId) { this.orderId = orderId; this.currentState = new CreatedState(); // 初始状态为已创建 } // 状态切换入口 public void setCurrentState(OrderState state) { this.currentState = state; } // 对外暴露的业务操作,委托给当前状态处理 public void pay() { currentState.pay(this); } public void deliver() { currentState.deliver(this); } public void cancel() { currentState.cancel(this); } }

4. 客户端调用示例(状态流转演示)

java
代码解读
复制代码
public class ClientDemo { public static void main(String[] args) { OrderContext order = new OrderContext("ORDER_1001"); // 支付操作:创建状态 → 支付状态 order.pay(); // 输出:支付流程 & 状态变更 // 发货操作:支付状态 → 发货状态 order.deliver(); // 输出:发货流程 & 状态变更 // 尝试重复支付(已支付状态不允许) try { order.pay(); } catch (IllegalStateException e) { System.out.println("异常:" + e.getMessage()); // 输出错误信息 } } }

三、进阶:构建健壮的状态机框架

1. 状态工厂(集中管理状态实例)

java
代码解读
复制代码
public class OrderStateFactory { private static final Map STATE_POOL = new EnumMap<>(StateType.class); static { STATE_POOL.put(StateType.CREATED, new CreatedState()); STATE_POOL.put(StateType.PAID, new PaidState()); // 注册所有状态类 } public static OrderState getState(StateType type) { return STATE_POOL.get(type); } } // 使用枚举定义状态类型(避免魔法值) enum StateType { CREATED, PAID, DELIVERED, CANCELED }

2. 状态转换校验(防止非法状态迁移)

java
代码解读
复制代码
public abstract class BaseOrderState implements OrderState { // 定义合法的状态转换规则 protected abstract Set allowedNextStates(); @Override public final void transitionTo(OrderContext context, StateType nextState) { if (allowedNextStates().contains(nextState)) { context.setCurrentState(OrderStateFactory.getState(nextState)); } else { throw new IllegalArgumentException( "非法状态转换:当前状态" + getCurrentState() + "不能转换为" + nextState ); } } } // 具体状态类实现合法转换规则 public class CreatedState extends BaseOrderState { @Override protected Set allowedNextStates() { return Set.of(StateType.PAID, StateType.CANCELED); // 仅允许支付或取消 } }

3. 可视化状态机(状态流转图)

支付
取消
发货
取消
确认收货
终止
已创建
已支付
已取消
已发货
已完成
已关闭

四、框架与源码中的状态模式实践

1. Spring State Machine(专业状态机框架)

  • 核心组件:

    • StateMachine:管理状态和转换
    • Transition:定义状态转换条件(如支付成功触发状态变更)
  • 使用示例:

    java
    代码解读
    复制代码
    // 定义订单状态和事件 StateMachine stateMachine = StateMachineBuilder .builder() .withStates() .initial(OrderState.CREATED) .state(OrderState.PAID) .end(OrderState.CANCELED, OrderState.COMPLETED) .withTransitions() .from(OrderState.CREATED).to(OrderState.PAID).on(OrderEvent.PAY) .build(); stateMachine.sendEvent(OrderEvent.PAY); // 触发状态转换

2. MyBatis 事务状态管理

  • Executor接口根据事务状态(自动提交 / 手动提交)切换执行逻辑
  • 通过BaseExecutor的子类(如SimpleExecutor、BatchExecutor)实现不同状态下的行为

3. TCP 连接状态(Java NIO 实现)

  • SelectionKey的状态(连接、可读、可写)通过状态模式管理事件分发
  • 避免大量if (key.isReadable())类型的条件判断

五、避坑指南:正确使用状态模式的 3 个要点

1. 避免状态爆炸(控制状态数量)

  • ❌ 反模式:为每个细小状态创建独立类(如订单的「支付中」「发货中」)
  • ✅ 最佳实践:
    • 合并相似状态(如「待审核」「审核中」合并为「审核状态」)
    • 使用状态工厂 + 枚举统一管理状态实例

2. 处理状态转换的原子性

  • 在分布式系统中,状态变更需结合分布式锁或事务保证原子性
java
代码解读
复制代码
// 分布式场景下的状态转换(伪代码) public void safeTransition(OrderContext context, StateType nextState) { String lockKey = "order_state_lock:" + context.getOrderId(); try (RedissonLock lock = redisson.getLock(lockKey)) { lock.lock(); currentState.transitionTo(context, nextState); } }

3. 状态类的职责单一性

  • 状态类应专注于状态相关行为,避免包含业务逻辑之外的代码
  • 复杂业务逻辑可提取为独立服务(如PaymentService、DeliveryService)

六、总结:何时该用状态模式?

适用场景核心特征典型案例
对象状态驱动行为不同状态下操作逻辑差异大,且状态可枚举订单状态机、电梯控制系统、工作流引擎
状态转换规则复杂需要集中管理合法的状态迁移路径游戏角色状态(战斗 / 待机 / 死亡)、设备状态(开机 / 待机 / 关机)
避免海量条件判断拒绝if-else地狱,追求代码可维护性编译器状态(词法分析 / 语法分析 / 语义分析)

状态模式通过「状态封装 + 行为委托」的设计,将状态相关的复杂性从业务逻辑中剥离,使系统在面对状态变化时更具弹性。下一篇我们将深入探讨责任链模式,解析从 Sentinel 流控到审批流程的链式处理逻辑,敬请期待!

扩展思考:状态模式 vs 策略模式

两者都通过「封装变化」实现行为切换,但核心目标不同:

模式变化维度状态关联典型应用
状态模式对象的状态(动态变化)状态之间存在依赖和转换状态机驱动的业务流程
策略模式算法或策略的选择(静态替换)无状态依赖,策略间独立不同排序算法、支付方式选择

理解这种差异,能帮助我们在设计时更精准地选择合适的模式。

注:本文转载自juejin.cn的AronTing的文章"https://juejin.cn/post/7493933353323282467"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

103
后端
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top