命令模式(command_pattern)

命令模式(Command Pattern)


命令模式將一個請求封裝爲一個對象,從而是你可用不同的請求對客戶進行參數化,對請求排隊或記錄請求日誌以及支持可撤銷的操作。


看個例子

一個場景:餐廳點餐,出餐

1)點餐:一個芝士漢堡,產生一個芝士漢堡的訂單(createOrder)

2)服務員拿走訂單(takeOrder)

3)把訂單交到後廚(orderUp)

3)廚師接過訂單,開始烹飪(make)

4)出餐

從這個流程來思考對象和方法的調用關係,對象的角色和職責

· 一張訂單封裝準備餐點的請求

把訂單想象成一個用來請求準備餐點的對象,訂單對象可以被傳遞。訂單的接口只包含一個方法就是orderUp()。這個方法封裝了準備餐點所需的動作。訂單有一個到“需要進行準備工作的對象”的引用。這一切都被封裝起來,所以服務員不需要知道訂單上有什麼,也不需要知道是誰來準備餐點;她只需要將訂單放到訂單窗口,說一聲訂單來了即可。

· 服務員的工作只有接收訂單,然後調用orderUp()方法

服務員的工作很簡單:接下顧客的訂單,繼續幫助下一個顧客,然後將一定數量的訂單放到訂單櫃檯,並調用orderUp(),讓人來準備餐點。服務員不需要擔心知道訂單的內容是什麼,或者由誰來準備餐點。只需要知道,訂單有一個orderUp()方法可以調用,這就夠了。

· 廚師具備準備餐點的知識

廚師是一種對象,他真正知道如何準備餐點。一旦服務員調用orderUp()的方法,廚師就接收,實現需要創建餐點的所有方法。服務員和廚師之間是徹底的解耦,服務員和廚師之間無須溝通,服務員的訂單封裝了餐點的細節,服務員只要調用每個訂單的方法即,而廚師看了什麼訂單就知道該做些什麼餐點。

例子的關鍵點在於,我們需要設計一種模型來將“發出請求的對象”和“接受與執行這些對象的請求”分隔開來。

從例子轉向命令模式

在這裏插入圖片描述

· 服務員 => Invoker

· 廚師 => Reveiver

· orderUp() => execute()

· 訂單 => Command

· 顧客 => Client

· takeOrder() => setCommand()


認識設計模式

一個命令對象通過在特定接收者上綁定一組動作來封裝一個請求。要達到這一點,命令對象將動作和接收者包進對象中。這個對象只暴露一個execute()方法,但此方法被調用的時候,接收者就會進行這些動作。從外面來看,其他對象不知道究竟哪個接收者進行了哪些動作,只知道如果調用execute()方法請求的目的就會達到。

在命令模式中,命令對象並不知道如何處理命令,會有相應的接收者對象來真正執行命令。就像訂單和廚師的關係。

命令模式的關鍵之處就是把請求封裝成對象,也就是命令對象,並定義統一的執行操作的接口,這個命令對象可以被存儲、轉發、記錄、處理、撤銷等,整個命令模式都是圍繞這個對象進行的。

命令模式類圖

  • Command:

    定義命令的接口,聲明執行的方法

  • ConcreteCommand:

    命令接口實現對象,是“虛”的實現;通常會從持有接收者,並調用接收者的功能來完成命令要執行的操作

  • Receiver:

    接收者,真正執行命令的對象。任何類都可能成爲一個接收者,只要它能夠實現命令要求實現的相應功能

  • Invoker:

    要求命令對象執行請求,通常會持有命令模式,可以持有很多的命令對象。這個是客戶端真正觸發命令並要求命令執行相應操作的地方,也就是說相當於使用命令對象的入口

  • Client:

    創建具體的命令對象,並且設置命令對象的接收者。注意這個不是我們常規意義上的客戶端,而是在組裝命令對象和接收者,或許,把這個Client稱爲裝配者會更好理解,因爲真正使用命令的客戶端是從Invoker來觸發執行。

在這裏插入圖片描述


優點

· 更鬆散的耦合
命令模式使得發起命令的對象 — 客戶端,和具體實現命令的對象 — 接收者對象完全解耦,也就是說發起命令的對象完全不知道具體實現對象是誰,也不知道如何實現。

· 更好的擴展性
由於發起命令的對象和具體的實現完全解耦,因此擴展新的命令就很容易,只需要實現新的命令對象,然後在裝配的時候,把具體的實現對象設置到命令對象中,然後就可以使用這個命令對象,已有的實現完全不用變化。

· 更動態的控制
命令模式把請求封裝起來,可以動態地對它進行參數化、隊列化和日誌化等操作,從而使得系統更靈活。


何時使用命令模式

· 如何需要抽象出需要執行地動作,並參數化這些對象,可以選用命令模式。將這些需要執行地動作抽象成爲命令,然後實現命令地參數化配置。

· 如果需要在不同地時刻指定、排列和執行請求,可以選用命令模式。

· 如果需要支持取消操作,可以選用命令模式,通過管理命令對象,能很容易地實現命令地回覆和重做功能。

· 在需要事務的系統中,可以選用命令模式。命令模式提供了對事務進行建模的方法。命令模式有一個別名就是Transaction。


範例代碼

代碼 :https://github.com/zxmfke/tech_learning_NoteOrBook/edit/master/design_pattern/command_pattern/example

代碼實現一個簡單的遙控器,通過設定不同的命令來控制電燈。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章