🎯 什麼情境該想到我
當你「一個物件的行為會隨它的內部狀態而大幅改變,程式裡因此塞滿了一堆判斷『現在是什麼狀態』的 if/switch」的時候(例如訂單/工單的狀態流轉、連線的斷開/連上、播放器的播放/暫停/停止)。
⚙️ 怎麼用(步驟 / 公式)
意圖:允許一個物件在其內部狀態改變時改變它的行為,讓這個物件看起來就像改變了它的類別。
主要參與者 / 結構:
- Context(環境):持有一個目前狀態物件的參照,把與狀態相關的行為委派給它。
- State(狀態介面):宣告各狀態下的行為方法。
- ConcreteState(具體狀態):各自實作在該狀態下的行為,並決定何時轉換到哪個狀態。
做法要點:
- 把每一種狀態抽成一個 State 類別,各自實作在該狀態下該有的行為。
- Context 不自己用條件分支判斷,而是把行為呼叫轉發給「當前狀態物件」。
- 狀態轉換由狀態物件自己(或 Context)負責:換掉 Context 持有的當前狀態即可。
- 新增狀態=新增一個類別,不必去改動散落各處的條件判斷。
🧪 我實際套用的紀錄
- (待填)
⚠️ 注意 / 什麼時候不適用
- 狀態很少、分支很單純時,套狀態模式是過度設計,直接用條件判斷更清楚。
- 每個狀態一個類別,狀態一多類別數量也跟著變多。
- 狀態間的轉換邏輯要想清楚放哪(狀態自身或 Context),否則轉換規則會散開難維護。
🔗 相關工具
- 策略模式 Strategy(結構幾乎相同:都把行為委派給一個介面物件;但意圖不同——策略是「選一種演算法」,狀態是「隨狀態自動切換行為並會自我轉換」)
- 備忘錄模式 Memento(可用來保存/還原 Context 的狀態)
- 單例模式 Singleton(無內部資料的狀態物件常做成共享單例以省記憶體)
- 工具-優先組合而非繼承(用組合持有狀態物件,取代滿地的條件分支)
- 工具-針對介面編程(Context 只依賴 State 介面)
- 設計模式