Command Pattern (命令模式) (Action) (Transaction)
命令模式是一種行為設計模式,可將請求封裝成物件,讓你可以將請求、佇列或紀錄等物件參數化,並支援可復原的的操作
命令模式結構

命令模式的應用場景
- 如果需要把動作變成參數化對象
命令模式可將特定的方法轉化成獨立對象。你可以將命令作為方法的參數進行傳遞,將命令保存在其他對象中,或是在執行期切換已連接的命令。
- 如果想要將動作放入隊列中、動作的執行或遠程執行動作
同其他對象一樣,命令也可以實現序列化,從而方便的寫入文件或數據庫中。一段時間後,再將他恢復成最初的命令對象。因此,可以延遲或計劃命令的執行。也可以將命令放入隊列、紀錄命令、通過網路傳送命令。
- 如果你想要實現操作回滾功能
盡管有很多方法可以實現撤銷和恢復功能,但命令模式是其中常用的一種。 為了能夠回滾操作,你需要實現已執行操作的歷史紀錄功能。對所有已執行命令對象及其相關程序狀態備份的 stack 結構,但是這種方法有兩個缺點。
-
程式狀態的保存功能並不容易實現,因為部分狀態為私有。可以使用備忘錄模式來在一定程度上解決這個問題。
-
備份狀態可能會占用大量內存。有時需要借助另一種實現方式:反向操作。反向操作也有代價:他可能會很難甚至無法實現。
-
使用時機
- 想參數化請求『欲執行的任務』時
- 依不同時間或佇列執行命令時
- 發送訊息者與接收執行者的生命週期不同時
- 讓執行的任務具有復原或日誌功能時
- 實作交易(Transaction)功能時
優缺點
⭕優點
- 單一職責原則。可以解藕觸發和執行操作的類。
- 開放封閉原則。可以在不修改已有客戶端程式碼的情況下,在程式碼中創建先的命令。
- 可以實現撤銷和恢復功能(Undoable Operations)
- 可以實現操作的延遲執行(Temporal Decoupling)
- 可以將一組簡單命令組合成一個複雜命令
❌缺點
- 程式碼會變得更加複雜,因為你在發送者和接收者之間增加了一個全新的層次。
命令模式(Command Pattern)
command 物件藉著將準備送給 receiver 的一組行動綁在一起,來封裝請求。command 物件將動作和 receiver 都包在它裡面,只公開一個方法 excute()。當你呼叫 execute()時,就會呼叫 receiver 的動作。在外面,其他的物件都不知道哪個 receiver 執行什麼動作,他們只知道呼叫 execute()方法之後,他們的請求就會被處理。
提示
命令模式可將請求封裝成物件,讓你可以將請求、佇列或紀錄等物件參數化,並支援可復原的的操作。
將『引發命令的物件』與『實際執行操作的物件』隔離開來
遇到的需求
- 我們想要設計一個控制器,上面可以登入很多設備,另外有 ON 和 OFF 的按鈕來控制設備,以及最後一個 UNDO 可以復原的按鈕

遇到的問題
- 廠商的類別有非常多,而且有著很不一樣的介面,因此希望遙控器不需要知道太多家電的介面細節,也不想在遙控器裡面有一堆家電的 if,(如: if slot1 == Light, then light.on())

命令物件
- 命令物件可以用特定的物件(例如客廳電燈物件)來封裝做某件事情的請求(例如打開電燈)
- 我們幫遙控器的按鈕指定一個命令物件,按下按鈕時,只需要呼叫命令物件做某項工作即可