3.8 状态模式
状态模式(State)允许一个对象在内部状态改变时改变它的行为,看起来就像换了一个类。它把“一坨随状态分支的 if/else / switch”重构成“每个状态一个对象”。
自动售货机是经典例子:同样是“按下出货按钮”,在“未投币”“已投币”“已售罄”状态下行为完全不同。下面的实验让你操作一台售货机,观察状态如何随动作迁移。
正在加载交互实验...
把状态做成对象
java
interface State {
void insertCoin(Machine m);
void pressButton(Machine m);
}
class NoCoinState implements State {
public void insertCoin(Machine m) { m.setState(new HasCoinState()); }
public void pressButton(Machine m) { System.out.println("请先投币"); }
}
class Machine {
private State state = new NoCoinState();
void setState(State s) { this.state = s; }
void pressButton() { state.pressButton(this); } // 委托给当前状态
}机器把每个动作委托给当前状态对象,由状态决定如何响应、以及切换到哪个状态。新增一个状态只需加一个类,不必去改满屏的条件分支。下面的红绿灯实验让你 next() 一步步推进,每个状态都知道自己的下一个状态。
正在加载交互实验...
正在加载概念检查...
状态 vs 策略:双胞胎的区别
两者的 UML 结构几乎一模一样(都把行为委托给一个接口对象),但意图不同:
| 状态模式 | 策略模式 | |
|---|---|---|
| 谁来切换 | 通常对象自己根据条件转换状态 | 通常客户端显式选定 |
| 是否有转换 | 状态之间会互相迁移 | 策略之间一般不互转 |
| 关注点 | 行为随状态变化 | 行为随算法选择变化 |
正在加载概念检查...
何时使用
当你发现一个类里充斥着 if (status == X) ... else if (status == Y) ...,而且这些分支在多个方法里重复出现时,状态模式能显著理清代码。订单生命周期、TCP 连接状态、游戏角色状态机,都是它的主场。
正在加载本节练习...