状态模式通过将订单各状态封装为独立类并实现统一接口,使状态转换逻辑解耦于订单主类,支持动态扩展与开闭原则,且禁止用枚举驱动状态决策。

状态模式是管理订单生命周期最清晰、可扩展性最强的方式之一,核心在于把每个状态封装成独立类,让状态转换逻辑从“if-else”或“switch”中解耦出来,避免在订单主类里堆积大量条件判断。
状态类职责单一,转换由状态自身决定
每个订单状态(如 待支付、已支付、已发货、已完成、已取消)都实现统一接口(如 OrderState),各自定义本状态下允许的操作及转换规则。比如:
-
待支付状态只响应
pay()→ 转为已支付;调用cancel()→ 转为已取消;其他操作(如发货)直接抛异常或忽略 -
已发货状态只接受
confirmReceipt()→ 转为已完成;拒绝重复发货或退款(除非额外支持)
这样,状态变更不再由订单对象判断“能不能做”,而是委托给当前状态对象——它最清楚自己能变成谁。
订单上下文只持有一个状态引用,不感知具体类型
订单类(Order)只需持有 OrderState 接口类型的字段,所有行为委托调用:
立即学习“Java免费学习笔记(深入)”;
public class Order {
private OrderState state;
public void pay() { state.pay(this); }
public void ship() { state.ship(this); }
public void confirm() { state.confirm(this); }
// 内部通过 state.changeState(...) 更新 this.state
}
状态实现类在执行动作后,主动调用 order.changeState(new ShippedState()),完成自我替换。订单本身完全不写 if (state == Paid) {...} 这类逻辑。
支持运行时动态扩展,新增状态零侵入
要加一个“部分退款中”状态?只需新增一个 PartialRefundingState 类,实现对应方法,并在合适位置触发切换(比如从 ShippedState 的 refundPart() 方法里)。无需修改已有状态类、订单主类或任何 if 分支——符合开闭原则。
若需记录状态变迁日志、校验权限、触发消息通知,也建议放在状态类内部(或通过策略注入),而不是堆在订单的每个方法里。
配合枚举+工厂可简化初始化,但别替代状态对象
启动时可用枚举映射初始状态(如 OrderStatus.CREATED → new CreatedState()),再交由工厂返回对应状态实例。但注意:枚举仅用于配置或序列化,**不能用来驱动状态逻辑**——否则又退化成 switch 判断。真正的决策必须发生在状态对象的方法体内。
状态间跳转应有明确契约(如只能从“已支付”到“已发货”,不可逆回),可在状态类构造或转换方法中做前置校验,避免非法流转。


















