状态模式通过将订单状态封装为独立对象实现解耦,订单类仅委托操作给当前状态对象,各状态类自行定义合法行为与流转规则,新增或修改状态无需改动主类,提升可维护性与扩展性。

用状态模式管理订单生命周期,核心是把“状态”变成可插拔的对象,而不是写一堆 if-else 判断当前是什么状态、能干什么事。订单本身不关心规则,只管把操作转发给当前状态对象;每个状态类自己清楚“我能响应什么动作”“下一步能变成谁”。这样新增状态、调整流转逻辑,都不用动订单主类,也不用改其他状态的代码。
状态接口统一行为契约
定义一个 OrderState 接口,声明所有状态共有的操作方法,比如 pay()、ship()、confirm()、cancel()。它不实现逻辑,只约定“订单在任意状态下都可能被要求做这些事”。接口里还可以加 getStateName() 方便日志或前端展示。
- 所有具体状态类(如 PendingPaymentState、PaidState、ShippedState)都实现这个接口
- 方法参数通常传入订单上下文(Order 或 OrderContext),方便状态类内部更新订单状态或调用业务服务
- 避免在接口里暴露状态枚举或字符串常量——这会把判断逻辑又拉回上层
每个状态类只做自己该做的事
待支付状态类只处理支付成功和取消;已支付状态类只响应发货和退款申请;已发货状态类只接受确认收货。其他非法操作,直接抛异常或打印明确提示,不静默忽略。
- 合法操作完成后,主动调用 context.setState(new XxxState()) 完成自我替换
- 校验逻辑(如库存是否充足、支付结果是否有效)放在具体状态的方法体内,不是由订单类判断后再决定调哪个方法
- 如果某状态需要触发外部调用(如调物流 API),就在这里做,保持职责内聚
订单上下文只负责委托和状态维护
Order 类或 OrderContext 类就是一个壳:持有一个 OrderState 类型的字段,提供 set/get 方法,所有业务方法(pay、ship 等)只是简单转发给当前 state 对象。
- 不出现
if (state instanceof PaidState)这类类型判断 - 不保存状态码或枚举值——状态对象本身即状态,无需额外标识
- 持久化交给 Service 层:状态变更后,由 Service 调用 DAO 更新数据库,而不是状态类直接操作 DB
Spring Boot 中可进一步解耦
在 Spring 环境下,可以把每个具体状态类标记为 @Component,再通过构造注入或 ApplicationContext 获取全部状态 Bean,构建状态映射表(比如用状态名字符串查到对应 State 实例),让状态机更灵活。
- 避免硬编码 new PaidState(),利于 AOP 增强或事务控制
- 配合 @Transactional,确保状态变更与数据库更新原子性
- 必要时可引入事件机制:状态切换后发布 OrderStateChangedEvent,供监听器处理通知、日志、风控等横切逻辑











