當物件的行為隨內部狀態劇烈改變,且狀態轉換邏輯散落在大量 if/else 或 switch 中時,狀態模式能將「每種狀態的行為」封裝為獨立類別,透過多型分派,消除條件判斷,符合開放封閉原則。
需求:單一按鈕控制門,初始關閉。按一下 → 開啟中;開啟中再按 → 關閉中;完全開啟後 2 秒自動關閉;開啟狀態下按一下 → 保持開啟 (禁止自動關閉)。

public class Door1 extends Observable {
public static final int CLOSED = 1, OPENING = 2, OPEN = 3, CLOSING = 4, STAYOPEN = 5;
private int state = CLOSED;
public void click() {
if (state == CLOSED) setState(OPENING);
else if (state == OPENING || state == STAYOPEN) setState(CLOSING);
else if (state == OPEN) setState(STAYOPEN);
else if (state == CLOSING) setState(OPENING);
}
private void setState(int state) {
this.state = state;
setChanged(); notifyObservers();
}
// ... status() 等輔助方法
}
缺點:狀態邏輯集中在 click(),新增狀態需修改此方法,違反 OCP;若有多個事件 (如 timeout、sensor) 需處理,if/else 會指數級膨脹。
public interface DoorState {
void click(DoorContext ctx);
void timeout(DoorContext ctx);
void sensor(DoorContext ctx);
String getName();
}
public class ClosedState implements DoorState {
public void click(DoorContext ctx) { ctx.setState(new OpeningState()); }
public void timeout(DoorContext ctx) {}
public void sensor(DoorContext ctx) {}
public String getName() { return "CLOSED"; }
}
public class OpeningState implements DoorState {
public void click(DoorContext ctx) { ctx.setState(new ClosingState()); }
public void timeout(DoorContext ctx) {} // 由硬體觸發完全開啟事件
public void sensor(DoorContext ctx) { ctx.setState(new OpenState()); } // 門已全開
public String getName() { return "OPENING"; }
}
// OpenState, ClosingState, StayOpenState 同理...
public class DoorContext extends Observable {
private DoorState state = new ClosedState();
public void setState(DoorState newState) {
this.state = newState;
setChanged(); notifyObservers();
}
public void click() { state.click(this); }
public void timeout() { state.timeout(this); }
public void sensor() { state.sensor(this); }
public String status() { return state.getName(); }
}
| 維度 | 傳統 if/else | 狀態模式 |
|---|---|---|
| 新增狀態 | 修改核心邏輯類 | 新增 State 實作類,零修改既有碼 |
| 程式碼分散度 | 集中在幾個巨大方法 | 分散於各 State 類,單一職責 |
| 測試性 | 需構建複雜前置條件 | 可單獨測試每個 State 行為 |
| 執行效能 | 多條件判斷 | 單一虛擬方法分派,極快 |
enum 實作狀態模式 (每個 enum 常數實作介面) 是輕量替代方案