系統中充滿「狀態」:執行緒生命週期、Hibernate 實體狀態、訂單流轉等。傳統用 if/else 或 switch 判斷會導致程式碼膨脹、難以維護,且新增狀態需修改多處邏輯。State 模式將每個狀態封裝為獨立類別,透過介面統一行為,符合開放封閉原則。
handle() 方法,內部靜態 List<State> commands 維持狀態順序。Create、Start、End、Destroy,各自實作 execute() 列印狀態名並觸發下一狀態。// State 介面
public interface State {
List<State> commands = new ArrayList<>();
void handle();
}
// Create 狀態
public class Create implements State {
public Create() { commands.add(this); }
public void handle() { execute(this); }
public void execute(State cmd) {
System.out.println("create");
commands.get(commands.indexOf(this) + 1).handle();
}
}
// Start、End 類似,略...
// Destroy 狀態(含遞迴循環陷阱)
public class Destroy implements State {
public Destroy() { commands.add(this); }
public void handle() { execute(this); }
public void execute(State cmd) {
System.out.println("destroy");
// 危險:循環呼叫導致 StackOverflowError
commands.get(commands.indexOf(this) >= commands.size() - 1 ? 0 : commands.indexOf(this) + 1).handle();
}
}
public class Main {
public static void main(String[] args) {
State s1 = new Create();
State s2 = new Start();
State s3 = new End();
State s4 = new Destroy();
s1.handle(); // 觸發鏈式反應
}
}
輸出結果:
create start end destroy create start end destroy ... (無限循環) Exception in thread "main" java.lang.StackOverflowError
Destroy 強制循環導致堆疊溢位。實務上應在最後狀態 handle() 中不再呼叫下一狀態,或引入 Context 物件管理狀態轉換邏輯。static List 導致所有實例共享同一序列,多執行緒或多流程下極易錯亂。建議改由 Context 持有狀態清單。Context 類別封裝狀態切換邏輯,解耦狀態類別間的依賴。enum 實作簡單狀態機(Java enum 可實作介面、擁有行為)。