状态模式通过将订单各状态(如待揽收、已揽收等)封装为独立类,实现行为与状态解耦;OrderContext委托状态类处理事件,配合配置化跳转规则和onEnter/onExit钩子,提升可维护性与可测试性。

直接用状态模式重构物流订单状态流转,核心是把“当前状态该做什么”这件事,从一堆条件判断里抽出来,交给对应的状态类自己管。不是写更多 if,而是让每个状态变成一个有行为、有责任的独立对象。
拆掉 if-else 嵌套,把状态变成类
物流订单常见状态如 待揽收、已揽收、运输中、派送中、已签收、已退货、已拒收,传统写法常在服务层堆砌判断:
- if (status == "已揽收") { 调用运单生成逻辑;校验承运商是否可用 }
- if (status == "派送中") { 检查配送员是否在线;触发短信通知 }
- ……
状态模式要求你为每个状态建一个类,比如 PickupState、InTransitState、DeliveringState,它们都实现统一接口 OrderState。这个接口定义通用行为,如 onEnter()(进入该状态时执行)、onExit()(离开时清理)、handleEvent()(响应事件)。
让上下文只做委托,不操心逻辑细节
OrderContext 是订单的持有者,它不判断“现在能干什么”,只负责:
- 保存当前状态对象引用(如
currentState = new PickupState()) - 暴露业务事件方法(如
confirmPickup()、startDelivery()) - 调用
currentState.handleEvent(this),把具体动作交给当前状态类去执行
例如,当调用 orderContext.confirmPickup(),PickupState 自己决定:记录揽收时间、生成运单号、通知仓库出库——这些逻辑完全隔离,其他状态类看不到也不需要知道。
状态跳转规则集中管理,支持动态扩展
跳转不能靠状态类自己瞎定,得有明确约束。推荐用配置驱动方式:
- 定义合法转换表:
["待揽收" → "已揽收"]允许,["已签收" → "已揽收"]禁止 - 在
OrderContext.transition(event)中校验:查表确认currentState::NAME + event是否有目标状态 - 新增“异常滞留”状态?只需加一个
StalledState类,更新配置表,不碰原有类
守卫条件(Guard)可写在状态类内部,比如 DeliveringState.onEnter() 检查配送员 GPS 是否在服务范围内,不满足则拒绝进入,避免无效跳转。
配合事件驱动与钩子,让动作自然发生
状态变化本身是业务节点,不是终点。每个状态切换前后,自动触发关联动作:
-
onEnter():发物流通知、扣减库存、更新 ES 索引 -
onExit():释放临时锁、归档旧日志、关闭定时任务 - 事件回调:外部系统推送“签收成功”,由
DeliveredState处理结算、启动售后倒计时
这种设计下,物流履约各环节(揽收、中转、末端)的差异逻辑被封装在各自状态类中,订单主流程干净清晰,测试也容易——每个状态类可单独单元测试其行为和边界条件。

















