命令模式:將「請求」封裝爲對象,以便使用不同的請求,隊列或者日誌來參數化其他對象。命令模式也支持可撤銷的操作。

命令模式把方法調用封裝起來,通過封裝方法調用,我們可以把運算塊包裝成形。所以調用此運算的對象不需要關心事情是如何進行的,只要知道如何使用包裝成形的方法來完成它就可以。

問題描述

上面的問題描述,看上去一頭霧水,我們只要記住命令模式的3個角色:調用者:按鈕;接收者:具體的裝置;命令:綁定給調用者的行爲。

1. 讓我們看看遙控器

整體的業務流程是:按鈕按下後,命令就調用action()函數,然後action()函數就會調用接收者的行爲。

2. 仔細看看裝置的類

思考一下:如果按照正常的寫法,我們是不是會直接在調用者中,實例化接收者,然後依次調用接收者的行爲類。

這種方法的缺陷,1. 簡單而言,耦合性太高;2. 然後呢,如果裝置改變了,那麼調用者的代碼就會跟着改變。

3. 命令模式

簡單而言,我們發現上面的缺陷是可以解決的,可以用命令模式將「動作的請求者」從「動作的執行者」對象中解耦。

可以這樣理解:調用者不直接調用執行者,而是綁定一個命令對象,用命令對象的方法去調用執行者、這個命令對象有實際的動作執行者,和action函數,所以成功解耦。

這樣來說,當我們裝置需要改變時,我們可以直接重新給調用者綁定一個命令對象即可。

下面展示通用的命令模式的類圖:

我們可以看到上面的調用者,命令類以及接收者三者的關係。

如果不是很清晰,沒有關係,我們實現以下遙控器的代碼就會更加清晰。

3.1 實現命令接口

3.2 實現一個打開電燈的命令(命令類中包含了接收者)

3.3 調用者(使用命令對象)

3.4 我們簡單的測試

如果,裝置換了,那麼我們重新setCommand()方法即可。

定義命令模式:我們知道一個命令對象通過在特定接收者上綁定一組動作來封裝一個請求。這個對象只暴露出一個execute()方法供調用者調用。

4. 我們基於命令模式實現遙控器

實現遙控器(調用者)

實現命令

讓我們開始測試遙控器

注意:

基於命令模式的類,我們給出遙控器的類圖

5. 實現undo()

我們需要在遙控器上面加上撤銷的功能,將上一個動作撤銷掉,很簡單,往下看。

還有一個問題,我們要讓遙控器追蹤到上一次按下的是什麼命令?然後基於該命令執行undo()

每個遙控器都需要有party模式,就是說一次調用很多個命令來運行

定義一個新命令,傳入一個命令的數組,然後依次執行即可。

6. 命令模式的應用

隊列請求

日誌請求

總結: