HeadFirst 設計模式學習筆記6--命令模式

1.這一節我們的任務是創建一個類似智能家居的萬能遙控器,控制各種家電。我們需要將“請求”封裝成對象(一個命令對象通過在特定接收者上綁定一組動作來封裝請求),以便使用不同的請求、隊列、或者日誌來參數化其對象——這就是命令模式。

2.我們具體來看一個例子:

首先我們要完成對命令的對象封裝:

只有一個方法,所有的具體命令的對象都要實現這個接口,這就做到了封裝,比如對於燈這個對象,

我們可以通過上述接口封裝“開燈”這個命令,這個就是所謂的命令對象,它把動作和接收者包進對象之中,只暴露一個execute方法:

而我們的遙控器對於上述封裝要一無所知,這樣才能做到解耦:

我們現在試着用一下這個遙控器,我們首先創建一個遙控器,然後創建開燈這個命令並置於其中,最後按下按鍵,這樣,遙控器不知道是哪個對象(實際上是燈)進行了哪個動作(實際上是開燈這個動作)就可以完成請求的發出。如此一來,遙控器和燈之間的耦合性就非常低了:

很簡單的,我們想要在一個遙控機中實現控制多個家電的能力就可以用一個數組來維護這樣的一組命令,可以看做提供了多個命令的插槽:

你可能會注意到一個叫做noCommand的對象出現在初始化遙控器對象時。這個是個小技巧,我們並不想每次都檢查某個插槽是不是都綁定了命令,那麼我們就引入了這個東東,實現一個不做事情的命令:

這樣初始化就讓每一個插槽都有命令了,以後若不進一步指明命令的插槽,那麼就是默認這個noCommand對象。這就是一個典型的“空對象”例子,當你不想返回一個有意義的對象時,空對象就十分有用,此時空對象可以做成判斷NULL或者提示“未綁定”信息的工作。

3.我們在命令模式中也可以設置類似undo的撤銷命令來撤銷發出的命令請求:

我們還是拿開電燈這個操作來說明,畢竟這足夠簡單:對於一個開燈命令,其對應的撤銷命令自然是“關電燈”:

雖然這簡單之極,這還沒完,我們必須讓遙控器記住上次到底做了什麼操作,纔可能去撤銷:

對於電燈,我們只有兩種狀態,但是要是多個狀態呢?我們舉一個吊扇的例子,吊扇有多個轉速,高中低關,四個狀態:

那麼在實現風扇各個轉速命令時,就要去記錄在執行這個命令前風扇的轉速,其撤銷命令中則根據記錄的部分完成undo操作。

當然你也可以實現諸如多個命令批量執行和完成多個撤銷操作。

命令模式可以用於工作隊列和日誌操作等方面。

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