iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0
自我挑戰組

設計模式探索系列 第 17

[Day 17] 命令模式 (1)

  • 分享至 

  • xImage
  •  

遙控器的設計

這章的設計目標是由"遙控器的設計"切入。設想現在有一個好幾個按鈕的遙控器,有2排各n個按鈕,讓使用者設定不同列的按鈕要操控不同的設備(意思就是最多可以設定對n個設備進行操作),以及一顆可以取消上一個命令的Undo按鈕,這就是我們的目標。而每個設備都有不同的介面,但希望這個遙控器是可以兼容目前及將來的各種設備。
就像這樣:
https://ithelp.ithome.com.tw/upload/images/20221002/20140096hvhvaC8lUr.png

而使用者可以決定把A設為電視的開關,把B設為電燈開關...等等,而按下Cancel則可以取消上一個動作,例如先選擇開燈按鈕後按Cancel,就可以取消開燈的動作。
而設備的介面自然是各式各樣...
https://ithelp.ithome.com.tw/upload/images/20221002/20140096TuIXFnAIZ0.png

要從何設計起呢?
從前面其他設計模式的經驗,可以知道一定要把介面跟實作細節切清楚,所以在遙控器裡面直接用if-else判斷目前的設備並發送命令肯定是行不通的。而這就是命令模式派上用場的時刻了...
我們必須要將 "操作的要求者─遙控器"實際執行該項操作的物件─各種設備 解耦合,使用 "命令物件" 來聯繫兩者達到操作的目的,意即命令物件會封裝設備物件以及執行動作細節。

這個模式實際如何設計?我們先切到另外一種情境...

餐廳的點餐流程

上面這幾個物件的關係可以用餐廳點餐的角色與流程來理解。

  1. 顧客訂單裡面添加內容,並把它交給服務生。=> createOrder()
    => 顧客建立的訂單,只需要確保它的介面有一個orderUp()即可,其他餐點的所有細節都封裝在訂單中。
  2. 服務生拿走訂單,並將訂單放在窗口。=>takeOrder()/orderUp()
    => 服務生不需要知道訂單的內容,只需要收取訂單,放在窗口並呼叫orderUp()來確保對應的廚師會來接手完成工作。
  3. 廚師依據訂單內容進行備餐。=>makeFood()
    => 廚師知道備餐的細節知識,orderUp()被呼叫後廚師就會來接手根據訂單內容來進行實作;廚師跟服務生是解耦合的,服務生只需要呼叫orderUp()方法,而廚師則是從訂單來了解動作細節。

回到遙控器範例:

  1. 顧客訂單裡面添加內容,並把它交給服務生
    => 每組按鈕是一個訂單,使用者在對應的位置按下按鈕
  2. 服務生拿走訂單,並將訂單放在窗口。
    => 遙控器不需要知道命令內容,只需要呼叫orderUp()來確保對應的設備會來接手完成工作。
  3. 廚師依據訂單內容進行備餐。
    => orderUp()被呼叫後設備就會來接手根據命令內容做出反應。

對應到命令模式

接著就可以回過頭來看命令模式的架構了。

  • 顧客 <-> client
  • 服務生 <-> Invoker
  • 廚師 <-> Receiver
  • 訂單 <-> Command
  • orderUp <-> execute
  • takeOrder <-> setCommand()

https://ithelp.ithome.com.tw/upload/images/20221002/20140096rgsyJCYU7z.png

接下來,就可以開始實作我們的遙控器啦!


上一篇
[Day 16] 單例模式 (2)
下一篇
[Day 18] 命令模式 (2)
系列文
設計模式探索30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言