設計模式之命令模式

2021-10-09 03:41:06 字數 2943 閱讀 1312

簡單的說,命令模式可將「動作的請求者」從「動作的執行者」物件中解耦。

將乙個請求封裝為乙個物件,從而使你可用不同的請求對客戶進行引數化(即,可以用不同的命令物件,去引數化配置客戶的請求);對請求排隊或記錄請求日誌,以及支援可撤銷的操作

這一模式的關鍵是乙個抽象的command類,它定義了乙個執行操作的介面。其最簡單的形式是乙個抽象的execute操作。具體的command子類將接收者作為其乙個例項變數,並實現execute操作,指定接收者採取的動作。而接收者有執行該請求所需的具體資訊。

接收者:真正執行命令的物件。任何類都可能成為乙個接收者,只要它能夠實現命令要求實現的相應功能。

結構

command:

定義命令的介面,宣告執行的方法。

concretecommand:

命令介面實現物件,是「虛」的實現;通常會持有接收者,並呼叫接收者的功能來完成命令要執行的操作。

receiver:

接收者,真正執行命令的物件。任何類都可能成為乙個接收者,只要它能夠實現命令要求實現的相應功能。

invoker:

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

client:

建立具體的命令物件,並且設定命令物件的接收者。注意這個不是我們常規意義上的客戶端,而是在組裝命令物件和接收者,或許,把這個client稱為裝配者會更好理解,因為真正使用命令的客戶端是從invoker來觸發執行。

流程

a) client建立乙個concretecommand物件並指定它的receiver物件。

b) 某invoker物件儲存該concretecommand物件。

c) 該invoker通過呼叫command物件的execute操作來提交乙個請求。若該命令是可撤銷的,cnocretecommand就在執行excute操作之前儲存當前狀態以用於取消該命令。

d) concretecommand物件會呼叫它的receiver的一些操作以執行該請求。

可撤銷的操作

可撤銷操作的意思就是:放棄該操作,回到未執行該操作前的狀態。

有兩種基本的思路來實現可撤銷的操作:

① 一種是補償式,又稱反操作式

比如被撤銷的操作是加的功能, 那撤消的實現就變成減的功能;同理被撤銷的操作是開啟的功能,那麼撤銷的實現就變成關閉的功能。

② 另外一種方式是儲存恢復式

意思就是把操作前的狀態記錄下來,然後要撤銷操作的時候就直接恢復回去就可以了。

認識命令模式

(1)命令模式的關鍵

命令模式的關鍵之處就是把請求封裝成為物件,也就是命令物件,並定義了統一的執行操作的介面,這個命令物件可以被儲存、**、記錄、處理、撤銷等,整個命令模式都是圍繞這個物件在進行。

(2)命令模式的組裝和呼叫

在命令模式中經常會有乙個命令的組裝者,用它來維護命令的「虛」實現和真實實現之間的關係。如果是超級智慧型的命令,也就是說命令物件自己完全實現好了,不需要接收者,那就是命令模式的退化,不需要接收者,自然也不需要組裝者了。

而真正的使用者就是具體化請求的內容,然後提交請求進行觸發就好了。真正的使用者會通過invoker來觸發命令。

在實際開發過程中,client和invoker可以融合在一起,由客戶在使用命令模式的時候,先進行命令物件和接收者的組裝,組裝完成後,就可以呼叫命令執行請求。

(3)命令模式的接收者

接收者可以是任意的類,對它沒有什麼特殊要求,這個物件知道如何真正執行命令的操作,執行時是從command的實現類裡面轉調過來。

乙個接收者物件可以處理多個命令,接收者和命令之間沒有約定的對應關係。接收者提供的方法個數、名稱、功能和命令中的可以不一樣,只要能夠通過呼叫接收者的方法來實現命令對應的功能就可以了。

(4)智慧型命令

在標準的命令模式裡面,命令的實現類是沒有真正實現命令要求的功能的,真正執行命令的功能的是接收者。

如果命令的實現物件比較智慧型,它自己就能真實地實現命令要求的功能,而不再需要呼叫接收者,那麼這種情況就稱為智慧型命令。

也可以有半智慧型的命令,命令物件知道部分實現,其它的還是需要呼叫接收者來完成,也就是說命令的功 能由命令物件和接收者共同來完成。

(5)發起請求的物件和真正實現的物件是解耦的

請求究竟由誰處理,如何處理,發起請求的物件是不知道的,也就是發起請求的物件和真正實現的物件是解耦的。發起請求的物件只管發出命令,其它的就不管了。

命令模式的更多用途

命令模式的關鍵之處就是把請求封裝成為物件,也就是命令物件(乙個接收者和一組動作),然後將它傳來傳去,就像是一般的物件一樣。現在,即使在命令物件被建立許久之後,運算依然可以被呼叫。事實上,它甚至可以在不同的執行緒中被呼叫。我們可以利用這樣的特性衍生一些應用,例如:執行緒池、工作佇列、日誌請求等。

佇列請求

想象有乙個工作佇列:你在某一端新增命令,然後另一端則是執行緒。執行緒進行下面的動作:從佇列中取出乙個命令,呼叫它的execute()方法,等待這個呼叫完成,然後將此命令物件丟棄,再取出下乙個命令…

請注意,工作佇列和命令物件之間是完全解耦的。此刻執行緒可能在進行財務運算,下一刻卻在讀取網路資料。工作佇列物件不在乎到底做些什麼,它們只知道取出命令物件,然後呼叫其execute()方法。類似地,它們只要實現命令模式的物件,就可以放入佇列裡,當執行緒可用時,就呼叫此物件的execute()方法。

日誌請求

某些應用需要我們將所有的動作都記錄在日誌中,並能在系統宕機之後,重新呼叫這些動作恢復到之前的狀態。

設計模式之命令設計模式

先來看一下命令模式的類圖 乍一看好像類很多,其實我們逐個分析他們。類圖中存在的類可以分為 invoker icommand conceretecommand receiver invoker類 上層直接調取invoker類 icommand 是對命令的抽象 conceretecommand 是命令的...

設計模式之命令模式

command pattern 將請求封裝成物件,這可以讓你使用不同的請求,佇列,或者是日誌請求來引數化其他物件,命令模式也可以支援撤銷操作。命令模式有兩種實現方式 1.在命令管理器中提供設定當前命令接受者的方法,當執行訊息或者是有訊息壓入的時候直接將命令傳送給當前設定的接受者。2.在命令管理器中建...

設計模式之命令模式

當我們有一台多功能的印表機,然後通過電腦直接進行任務,如圖 如果通過這樣的設計直接去呼叫多功能一體機的功能,就會存在此時此刻只能進行乙個任務,不允許有多個客戶端同時操作.那麼現在我們就需要考慮一種新的設計模式,叫做命令設計模式。命令設計模式 將乙個請求封裝為乙個物件,從而使你可用不同的請求對客戶進行...