状态模式是一种行为型设计模式,其核心思想是:当一个对象的内部状态改变时,它的行为也会随之改变,就像对象的 “类” 发生了变化一样。该模式通过将对象不同状态对应的行为封装到独立的 “状态类” 中,让对象在不同状态下切换时,只需切换对应的状态对象,而非通过大量if-else或switch判断状态。
状态模式的本质是 “将状态与行为绑定,并用状态对象管理状态切换” —— 对象本身不直接维护状态和实现状态对应的行为,而是委托给当前的 “状态对象”,从而简化状态管理逻辑,提高代码可维护性和扩展性。

状态模式的典型应用场景如下:
- 对象状态较多且状态切换频繁:
- 订单系统:待支付→已支付→已发货→已完成→已取消(多状态流转);
- 电梯系统:停止→上升→下降→开门→关门(不同状态下行为不同,如 “上升中” 不可开门)。
- 对象行为随状态变化而变化:
- 播放器:播放中(可暂停 / 停止)→暂停中(可播放 / 停止)→停止中(可播放);
- 网络连接:连接中(可发送数据 / 断开)→断开中(可重连)→重连中(可取消重连)。
- 避免大量条件判断:
- 传统代码:
if (state == 待支付) { 执行支付逻辑 } else if (state == 已支付) { 执行发货逻辑 };
- 状态模式:将每个
if 分支的逻辑封装到独立状态类,环境类直接委托给当前状态。
下面我将用 Java 代码实现状态模式,以订单状态流转为例,展示不同状态下订单行为的变化。
首先,我们根据业务场景将状态分为支付、运输和确认收货三个状态,然后把他们封装到一个状态类中
1 2 3 4 5 6 7 8 9 10 11 12
| public abstract class State { public abstract void pay(Order order); public abstract void ship(Order order); public abstract void confirmReceipt(Order order); }
|
然后,我们定义具体的状态类,他们都继承这个State抽象类,但是只能执行自己的状态操作。定义如下:
- PendingPaymentState(待支付状态):只能执行支付操作,支付后切换到已支付状态
- PaidState(已支付状态):只能执行发货操作,发货后切换到已发货状态
- ShippedState(已发货状态):只能执行确认收货操作,确认后切换到已完成状态
- CompletedState(已完成状态):不能执行任何操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class PendingPaymentState extends State { @Override public void pay(Order order) { System.out.println("订单 " + order.getOrderId() + " 支付成功"); order.setState(new PaidState()); } @Override public void ship(Order order) { System.out.println("错误:订单 " + order.getOrderId() + " 尚未支付,不能发货"); } @Override public void confirmReceipt(Order order) { System.out.println("错误:订单 " + order.getOrderId() + " 尚未支付,不能确认收货"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class PaidState extends State { @Override public void pay(Order order) { System.out.println("错误:订单 " + order.getOrderId() + " 已经支付,不能重复支付"); } @Override public void ship(Order order) { System.out.println("订单 " + order.getOrderId() + " 已发货"); order.setState(new ShippedState()); } @Override public void confirmReceipt(Order order) { System.out.println("错误:订单 " + order.getOrderId() + " 尚未发货,不能确认收货"); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class ShippedState extends State { @Override public void pay(Order order) { System.out.println("错误:订单 " + order.getOrderId() + " 已经支付并发货,不能再次支付"); } @Override public void ship(Order order) { System.out.println("错误:订单 " + order.getOrderId() + " 已经发货,不能重复发货"); } @Override public void confirmReceipt(Order order) { System.out.println("订单 " + order.getOrderId() + " 已确认收货"); order.setState(new CompletedState()); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class CompletedState extends State { @Override public void pay(Order order) { System.out.println("错误:订单 " + order.getOrderId() + " 已完成,无需支付"); } @Override public void ship(Order order) { System.out.println("错误:订单 " + order.getOrderId() + " 已完成,无需发货"); } @Override public void confirmReceipt(Order order) { System.out.println("错误:订单 " + order.getOrderId() + " 已完成,不能重复确认收货"); } }
|
定义好这些状态后,我们的订单对象中就可以维护这个订单的当前状态、提供状态切换的方法,但具体的状态切换后执行的动作,延迟到具体的状态类中执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class Order { private State currentState; private final String orderId; public Order(String orderId) { this.orderId = orderId; this.currentState = new PendingPaymentState(); } public void setState(State state) { this.currentState = state; } public String getOrderId() { return orderId; } public void pay() { currentState.pay(this); } public void ship() { currentState.ship(this); } public void confirmReceipt() { currentState.confirmReceipt(this); } }
|
最后,我们看客户端调用代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Client { public static void main(String[] args) { Order order = new Order("ORD-123456"); order.pay(); order.ship(); order.confirmReceipt(); order.pay(); order.ship(); } }
|
上面的代码中:
- 订单创建时初始化状态为待支付状态
- 当调用订单的某个行为方法(如 pay ())时:
- 订单将请求委托给当前状态对象
- 状态对象执行该状态下的具体逻辑
- 如果操作有效,状态对象会通过订单的 setState () 方法切换到新状态
- 状态切换后,订单的后续行为将由新的状态对象处理
这种设计模式的优势在于:
- 避免了大量的 if-else 条件判断,代码结构更清晰
- 每个状态的行为被封装在独立的类中,职责单一
- 新增状态只需添加新的状态类,符合开闭原则
- 状态切换逻辑集中在状态类中,便于维护和扩展