
你看過這種 code 嗎?
if (order.status === 'pending') { /* ... */ }
else if (order.status === 'processing') { /* ... */ }
else if (order.status === 'shipped') { /* ... */ }
else if (order.status === 'completed') { /* ... */ }而且這段 code 出現在五個不同的地方。每次新增一個狀態,你就要改五處。改漏一處?恭喜,出 bug 了。
先講結論
State Pattern 把每個狀態的行為封裝成獨立的 class。物件不再用 if-else 判斷「我現在是什麼狀態」,而是直接委託給當前狀態物件處理。狀態自己知道自己能做什麼、不能做什麼,也知道下一步該切換到哪個狀態。
classDiagram class Order { -state : OrderState +setState(state) void +process() void +ship() void +complete() void } class OrderState { <<interface>> +process()* void +ship()* void +complete()* void } class PendingState { +process() void +ship() void +complete() void } class ProcessingState { +process() void +ship() void +complete() void } class ShippedState { +process() void +ship() void +complete() void } Order o-- OrderState : 持有當前狀態 OrderState <|.. PendingState OrderState <|.. ProcessingState OrderState <|.. ShippedState
實戰:訂單狀態流轉

class Order {
constructor() {
this.state = new PendingState(this);
}
setState(state) { this.state = state; }
process() { this.state.process(); }
ship() { this.state.ship(); }
complete() { this.state.complete(); }
}
class PendingState {
constructor(order) { this.order = order; }
process() {
console.log('開始處理訂單...');
this.order.setState(new ProcessingState(this.order));
}
ship() { console.log('還沒處理,不能出貨'); }
complete() { console.log('還沒出貨,不能完成'); }
}
class ProcessingState {
constructor(order) { this.order = order; }
process() { console.log('已經在處理了'); }
ship() {
console.log('訂單出貨中...');
this.order.setState(new ShippedState(this.order));
}
complete() { console.log('還沒出貨,不能完成'); }
}
class ShippedState {
constructor(order) { this.order = order; }
process() { console.log('已經出貨了'); }
ship() { console.log('已經出貨了'); }
complete() {
console.log('訂單完成!');
// 可以切換到 CompletedState
}
}
const order = new Order();
order.ship(); // 還沒處理,不能出貨
order.process(); // 開始處理訂單...
order.ship(); // 訂單出貨中...
order.complete(); // 訂單完成!注意 order.ship() 在 Pending 狀態下會被擋掉——不用寫 if-else,PendingState 自己就會處理。
State vs Strategy:到底差在哪?
結構幾乎一模一樣,但意圖完全不同:
- State:狀態由內部自動切換(「訂單處理完了,自動變成 shipped」)
- Strategy:策略由外部主動選擇(「這次用黑五折扣」)
如果你的物件會「自己變」,用 State。如果是「別人幫它換」,用 Strategy。
State Pattern 就像交通號誌——紅燈的時候不能走、綠燈的時候可以走,燈號自己會換。只是有些人紅燈也照走不誤。