這章的設計目標是由"遙控器的設計"切入。設想現在有一個好幾個按鈕的遙控器,有2排各n個按鈕,讓使用者設定不同列的按鈕要操控不同的設備(意思就是最多可以設定對n個設備進行操作),以及一顆可以取消上一個命令的Undo
按鈕,這就是我們的目標。而每個設備都有不同的介面,但希望這個遙控器是可以兼容目前及將來的各種設備。
就像這樣:
而使用者可以決定把A設為電視的開關,把B設為電燈開關...等等,而按下Cancel則可以取消上一個動作,例如先選擇開燈按鈕後按Cancel,就可以取消開燈的動作。
而設備的介面自然是各式各樣...
要從何設計起呢?
從前面其他設計模式的經驗,可以知道一定要把介面跟實作細節切清楚,所以在遙控器裡面直接用if-else
判斷目前的設備並發送命令肯定是行不通的。而這就是命令模式派上用場的時刻了...
我們必須要將 "操作的要求者─遙控器" 與 實際執行該項操作的物件─各種設備 解耦合,使用 "命令物件" 來聯繫兩者達到操作的目的,意即命令物件會封裝設備物件以及執行動作細節。
這個模式實際如何設計?我們先切到另外一種情境...
上面這幾個物件的關係可以用餐廳點餐的角色與流程來理解。
createOrder()
orderUp()
即可,其他餐點的所有細節都封裝在訂單中。takeOrder()
/orderUp()
orderUp()
來確保對應的廚師會來接手完成工作。makeFood()
orderUp()
被呼叫後廚師就會來接手根據訂單內容來進行實作;廚師跟服務生是解耦合的,服務生只需要呼叫orderUp()
方法,而廚師則是從訂單來了解動作細節。回到遙控器範例:
orderUp()
來確保對應的設備會來接手完成工作。orderUp()
被呼叫後設備就會來接手根據命令內容做出反應。接著就可以回過頭來看命令模式的架構了。
接下來,就可以開始實作我們的遙控器啦!