21.设计模式-STATE(状态)
一、模式定义与核心思想
状态模式是一种行为型设计模式,其核心目标是允许对象在其内部状态改变时改变行为,使对象的表现如同动态切换了类。该模式通过将状态逻辑封装到独立类中,解决以下问题:
- 消除条件分支:避免因状态判断产生的庞大
if-else或switch-case语句(如电商订单状态流转时需判断多种条件)。 - 状态与行为解耦:每个状态对应独立类,新增状态只需扩展子类,符合开闭原则。
- 动态行为切换:运行时通过替换状态对象实现行为变化(如游戏角色在行走、攻击状态下的不同响应)。
核心价值:
- 封装性:状态转换规则由具体状态类控制,外部无需感知细节。
- 可维护性:状态逻辑局部化,修改单一状态不影响其他逻辑。
- 扩展性:新增状态时无需修改上下文类(Context),仅需添加新状态类。
典型应用场景:
- 订单生命周期管理(待支付、已发货、已完成等状态)
- TCP连接状态机(建立连接、传输数据、断开连接)
- 交通信号灯控制(红、黄、绿灯状态切换)
- 游戏角色行为(移动、攻击、防御状态)
二、模式组成与UML类图
核心角色
- Context(上下文):
-
- 持有当前状态对象,定义客户端接口(如
Order类管理订单状态)。 - 委托状态相关操作给当前状态对象(如调用
state.handle())。
- 持有当前状态对象,定义客户端接口(如
- State(抽象状态):
-
- 声明状态处理接口(如
handle()方法),定义状态通用行为。
- 声明状态处理接口(如
- ConcreteState(具体状态):
-
- 实现特定状态下的行为逻辑(如
PaidState处理支付完成后的操作)。 - 可触发状态转换(如处理完成后将上下文状态设为
ShippedState)。
- 实现特定状态下的行为逻辑(如
UML类图
classDiagram
class Context {
-state: State
+setState(State)
+request()
}
class State {
<<interface>>
+handle(Context)
}
class ConcreteStateA {
+handle(Context)
}
class ConcreteStateB {
+handle(Context)
}
Context --> State : 委托行为
State <|-- ConcreteStateA
State <|-- ConcreteStateB

三、代码实现示例
场景:实现电商订单状态流转(待支付 → 已支付 → 已发货)
1. 抽象状态与上下文类
// 抽象状态接口
interface OrderState {
void handle(OrderContext context);
}
// 上下文类(订单)
class OrderContext {
private OrderState currentState;
public OrderContext(OrderState initialState) {
this.currentState = initialState;
}
public void setState(OrderState newState) {
this.currentState = newState;
}
public void process() {
currentState.handle(this);
}
}
2. 具体状态类实现
// 待支付状态
class UnpaidState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("处理支付逻辑...");
context.setState(new PaidState());
}
}
// 已支付状态
class PaidState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("生成发货单...");
context.setState(new ShippedState());
}
}
// 已发货状态
class ShippedState implements OrderState {
@Override
public void handle(OrderContext context) {
System.out.println("通知用户收货...");
}
}
3. 客户端调用
public class Client {
public static void main(String[] args) {
OrderContext order = new OrderContext(new UnpaidState());
order.process(); // 输出:处理支付逻辑...
order.process(); // 输出:生成发货单...
order.process(); // 输出:通知用户收货...
}
}
四、工业级源码应用
- Java AWT/Swing事件处理:
-
javax.swing.JButton的状态管理(正常、按下、禁用)通过内部状态类实现。
- Spring状态机(Spring Statemachine):
-
- 使用状态模式管理复杂业务流程(如订单审批流程的多级状态转换)。
- Android Activity生命周期:
-
Activity的onCreate、onPause等方法本质是状态转换,通过状态模式管理资源。
- TCP协议栈实现:
-
- 连接状态(SYN_SENT、ESTABLISHED、CLOSE_WAIT)通过状态类处理数据包响应。
- 游戏引擎(Unity/Unreal):
-
- 角色状态机(Idle、Run、Attack)通过
State子类实现动画和物理效果切换。
- 角色状态机(Idle、Run、Attack)通过
五、模式优劣与最佳实践
优势:
- 代码清晰度提升:状态逻辑集中管理,减少50%以上的条件分支。
- 动态扩展能力:新增状态只需添加类,无需修改现有代码(如电商新增“退款中”状态)。
局限性:
- 类数量膨胀:状态较多时需创建大量子类(可通过享元模式共享无状态对象优化)。
- 状态转换复杂性:跨状态依赖可能需引入中介者模式协调。
最佳实践:
- 状态机与策略模式结合:用状态机库(如Apache Commons SCXML)管理复杂转换规则。
- 异步状态处理:结合线程池处理高并发场景(如支付回调触发的状态变更)。
- 状态持久化:通过数据库或Redis存储当前状态,支持系统重启后恢复。
总结
状态模式如同软件系统的“动态基因”,通过行为与状态的动态绑定,在电商、游戏、网络协议等领域展现了强大的生命力。其设计精髓在于将状态逻辑原子化,开发者需重点把控状态转换的边界条件与性能平衡,结合具体场景选择显式/隐式状态切换策略,从而构建出高内聚、低耦合的弹性系统架构。

浙公网安备 33010602011771号