Head First 設計模式 —— 06. 命令 (Command) 模式
阿新 • • 發佈:2021-01-09
命令模式
將“請求”封裝成物件,以便使用不同的請求、佇列或者日誌來引數化其他物件。命令模式也支援可撤銷的操作。 P206
特點
- 使請求呼叫者和請求接收者解耦
P207
- 適合用來建立有彈性的設計,維持開閉原則 (同裝飾器模式
P104
) - 使用巨集命令可以一次執行其他一系列命令
P225
缺點
- 存大量具體的命令類
思考題
命令模式的設計如何支援請求呼叫者和請求接收者之間的解耦? P207
- 通過將請求接受者封裝進一個命令物件,並將請求接收者的一系列動作封裝成一個命令物件的方法,使得請求呼叫者只用持有命令物件,而不用關心其內部的請求接受者。請求呼叫者不知道哪個請求接受者執行了哪些動作。
P206
空物件
當不想返回一個有意義的物件是,可以使用空物件;也可以將處理 null
的責任轉義給空物件。 P214
- Java8 中的
java.util.Optional<T>
就通過使用空物件的方式,讓使用者可以進行鏈式呼叫,而不用主動處理null
。
思考題
我們的巨集命令唯一缺少的是撤銷功能。一個巨集命令被執行完,然後按下撤銷按鈕,那麼巨集內所進行的每一道命令都必須被撤銷。請在下面程式碼中,填入 undo()
方法的內容: P214
public class MacroCommand implements Command { Command[] commands; public MacroCommand(Command[] commands) { this.commands = commands; } public void execute() { for(int i = 0; i < commands.length; ++i) { commands[i].execute(); } } public void undo() { // 想到動作可能和當前狀態有關,所以逆序撤銷 for(int i = commands.length - 1; i >= 0; --i) { commands[i].undo(); } } }
思考題
你認為 Web 伺服器如何應用這樣的佇列方式?還能想到任何其他的應用嗎? P228
- 所有請求都先放入一個工作佇列中,然後請求處理器不斷從工作佇列中取請求進行處理。
任務的非同步呼叫使用了工作佇列。
所思所想
- 剛看完書感覺命令模式和策略模式沒有太大區別,後來閱讀其他資料並仔細思考了一下,認為他們的側重點不一樣。策略模式側重於執行某一個動作的不同實現邏輯,而命令模式側重於執行不同的動作。(應該可以這樣理解:策略模式只知道做什麼動作,不知道動作如何完成;命令模式既不知道做什麼動作,也不知道動作如何完成。)
- 學了命令模式才發現,好多常用的寫法/工具(執行緒池、工作佇列、事件監聽器等)都是運用了命令模式。覺得觀察者模式中的
Observer
Observer
就是Command
,Observer
列表就是Command
列表。
本文首發於公眾號:滿賦諸機(點選檢視原文) 開源在 GitHub :reading-notes/head-first-design-patterns