狀態模式屬於行為型模式,其核心思想是:允許對象在內部狀態改變時改變它的行為,對象看起來似乎修改了它的類。將每種狀態封裝為獨立類別,並將狀態轉移邏輯分散到各狀態類中,避免龐大的 if-else 或 switch 判斷。
當一個對象的行為取決於其狀態,且狀態之間存在頻繁切換時:
if (state == A) ... else if (state == B) ... 判斷。注意區分「普通條件判斷」與「狀態切換」:前者是根據外部變量決定輸出,後者是狀態自我流轉(如開關燈:關→開→關)。
重構前:Context 中包含龐大的 push()/pull() 邏輯,狀態轉移硬編碼。
重構後:
// 1. 抽象狀態
public abstract class State {
public abstract void handlePush(Context c);
public abstract void handlePull(Context c);
public abstract Color getColor();
}
// 2. 具體狀態
public class RedState extends State {
public void handlePush(Context c) { c.setState(new BlueState()); }
public void handlePull(Context c) { c.setState(new GreenState()); }
public Color getColor() { return Color.RED; }
}
// BlueState, GreenState 類似...
// 3. Context 精簡為委派者
public class Context {
private State state;
public void setState(State s) { this.state = s; }
public void push() { state.handlePush(this); }
public void pull() { state.handlePull(this); }
}
| 優點 | 缺點 |
|---|---|
| 消除巨大條件分支,代碼清晰 | 增加類的數量,結構複雜化 |
| 狀態轉移邏輯集中在具體狀態類,易維護 | 若狀態轉移極簡單(如單純賦值),引入模式反而過度設計 |
| 新增狀態只需新增類,符合開閉原則 | 狀態類之間可能產生依賴 |
當狀態行為邏輯「足夠複雜」且「頻繁切換」時才使用。若只是簡單的布林標誌切換,if-else 更直接。記住:模式是為了解決複雜性,而非製造複雜性。