Java状态机模式通过State接口和具体状态类实现职责分离与多态调度,context委托操作、状态单例化、转换预构建及异步副作用保障高吞吐与可维护性。

Java 中用面向对象的状态机设计模式管理复杂对象状态,核心是把“状态”从数据变成行为载体,让每个状态自己决定能做什么、能变成谁、在什么条件下变。它不是给状态起个名字再 if-else,而是通过职责分离和多态调度,把混乱的判断逻辑收束到清晰、可测、可扩展的结构里。
用抽象状态接口统一契约
定义一个 State 接口(或抽象类),声明所有可能触发的操作方法,比如 pay()、ship()、cancel()、approve()。这些方法都接收上下文对象(如 OrderContext)作为参数,不依赖内部字段存业务数据。
- 接口只管“有哪些动作”,不管“怎么做”,为后续扩展留出空间
- 方法签名带 context,方便状态类内部调用
context.setState(new NextState())完成流转 - 可提供默认实现(如抛
UnsupportedOperationException),让非法操作有统一兜底
每个具体状态专注本职行为
为每个业务状态(如 PendingPaymentState、PaidState、ShippedState)创建独立类,实现 State 接口。它们只处理自己合法的动作,其余一律拒绝。
-
PendingPaymentState.pay()执行支付校验,成功后主动切换到PaidState -
PaidState.ship()检查库存与发货权限,通过则设为ShippedState -
ShippedState.cancel()直接抛异常或返回失败结果,因为已发货不可取消 - 所有状态类不保存 orderId、user、time 等运行时数据——这些全由 context 承载并传入
上下文类只做委托与托管
Context 类(如 OrderContext)持有当前状态引用,对外暴露统一入口(如 handlePay()),但内部不做任何条件判断,只是原样委托给当前状态对象。
立即学习“Java免费学习笔记(深入)”;
- 初始化时指定首状态:
this.state = new PendingPaymentState() - 所有操作都走
state.xxx(this),完全解耦控制流 - 状态字段建议用
final State+ setter 替换,防止意外篡改 - 可选增强:在
setState()前查预加载的转换表,拦截非法跳转(如从 CANCELLED 跳回 PAID)
工程级优化保障高吞吐与可维护性
面对百万级订单或频繁状态变更,纯 OOP 结构需配合关键工程手段:
- 状态实例必须轻量:全部用单例(
PaidState.INSTANCE),禁止每次 new - 转换逻辑预构建:启动时生成
Map<State, Map<Event, State>>,用 EnumMap 提速查找 - 副作用必须异步:状态切换只做两件事——校验 + 更新
context.state;发消息、写 DB、调第三方全走事件监听器 - 超 50 状态或含动态条件(金额/角色/时间)时,及时引入 DSL(YAML 描述流转)或 Spring StateMachine 等引擎,别硬扛


















