《状态模式》|设计模式系列第18篇
系列:行为型模式 · 状态模式(State Pattern)
关键词:状态切换、状态封装、行为随状态改变、消除大量if/else
一、什么是状态模式
状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
属于行为型设计模式。

简单理解:
将对象的每一种状态单独封装成独立状态类。上下文(Context)持有当前状态对象;当状态切换时,上下文把请求转发给当前状态对象执行。不同状态下同一个接口会执行不同逻辑,消除臃肿的 if/else 或者 switch 判断。
例子:订单,有 Unpaid、Paid、Shipped、Finished 等状态。不同状态下,cancel、pay、ship 行为规则不一样。
核心意图
把各个状态对应的行为封装为独立类;状态变化自动切换行为,避免大量条件分支。
适用场景
- 对象行为依赖自身状态,并且运行时状态会发生变化
- 业务逻辑充斥大量 if/else 或者 switch,按状态分支
- 状态和对应的动作经常需要扩展
- 状态机、订单流转、工作流、游戏角色状态
⚠️ 缺点预警:状态数量多时,会生成大量状态类;状态切换逻辑分散在各个状态类,整体阅读难度上升。
二、UML结构图
角色划分:
- Context(上下文):持有当前State引用,对外暴露业务方法,转发请求给状态对象
- State(抽象状态):定义所有状态共用的行为接口
- ConcreteState(具体状态):实现State接口,处理对应状态逻辑,可触发上下文状态切换
- Client(客户端):创建Context,发起调用

三、Java 完整示例
场景:Order 订单流转,状态:Unpaid,Paid,Shipped。
支持操作:pay、ship。代码全部使用英文。
1. State 抽象状态
public abstract class OrderState {
protected OrderContext context;
public void setContext(OrderContext context) {
this.context = context;
}
public abstract void pay();
public abstract void ship();
}
2. ConcreteState 具体状态
public class UnpaidState extends OrderState {
@Override
public void pay() {
System.out.println("Order paid successfully");
context.setState(new PaidState());
}
@Override
public void ship() {
System.out.println("Cannot ship, order is unpaid");
}
}
public class PaidState extends OrderState {
@Override
public void pay() {
System.out.println("Order already paid");
}
@Override
public void ship() {
System.out.println("Order shipped successfully");
context.setState(new ShippedState());
}
}
public class ShippedState extends OrderState {
@Override
public void pay() {
System.out.println("Cannot pay, order already shipped");
}
@Override
public void ship() {
System.out.println("Order already shipped");
}
}
3. Context 上下文
public class OrderContext {
private OrderState state;
public OrderContext() {
this.state = new UnpaidState();
state.setContext(this);
}
public void setState(OrderState state) {
this.state = state;
state.setContext(this);
}
public void pay() {
state.pay();
}
public void ship() {
state.ship();
}
}
4. Client 客户端
public class Client {
public static void main(String[] args) {
OrderContext order = new OrderContext();
order.pay();
order.ship();
order.pay();
order.ship();
}
}
运行输出:
Order paid successfully
Order shipped successfully
Cannot pay, order already shipped
Order already shipped
四、状态模式 vs 策略模式
| 模式 | 目标 | 核心 |
|---|---|---|
| State | 对象内部状态变化,自动切换行为;状态之间可以互相转换 | 状态是对象内部属性,状态类知道其他状态 |
| Strategy | 客户端主动替换算法;算法之间独立,互不感知 | 算法是可选方案,由客户端选择替换 |
五、优缺点总结
✅ 优点
- 消除大量 if/else 条件分支,代码按状态拆分
- 新增状态只需要新增状态类,符合开闭原则
- 状态逻辑内聚在各自状态类,单一职责
- 状态流转清晰,适合状态机业务
❌ 缺点
- 状态种类多的时候,类数量快速膨胀
- 状态切换逻辑分散在各个状态类,不方便全局查看完整流转图
- 理解门槛高于简单if分支
六、框架源码应用
- Spring StateMachine 状态机
- JDK
java.util.Scanner状态处理 - Activiti / Flowable 工作流状态
七、小结
状态模式核心:把每个状态封装为独立类,上下文持有当前状态,请求转发给状态对象执行;状态变更自动改变对象行为。
优先选择场景:订单、审批、工作流等状态驱动业务,if/else分支随状态持续增多。
0 条笔记