一、命令(Command)模式的結構
命令模式把一個請求或者操作封裝到一個對象中。命令模式允許系統使用不同的請求把用戶端參數化,對請求排隊或者記錄請求日誌,可以提供命令的撤銷和恢複功能。
命令模式是對命令的封裝。命令模式把發出命令的責任和執行命令的責任分割開,委派給不同的對象。命令模式類似C語言的回調。因為java不支援函數指標,所以命令模式可以達到同樣的目的。
結構圖如所示:
客戶角色代碼如下:
public class Client{
public static
void main(String [] args){
Receiver receiver =
new Receiver();
Command command = new
ConcreteCommand(receiver);
Invoker invoker = new
Invoker(command);
invoker.action();
}
}
一個具體命令與一個接收者綁定,在具體命令裡面調用接收者的處理方法,而用戶端的請求可以調用不同的命令對象。如果要增加一個新的命令,只需要增加新的具體命令對象和接收者,而不需要改動用戶端代碼,用戶端也不會察覺。
二、 命令模式在java中的應用
AWT的事件處理
Java語言使用了命令模式處理java.awt庫的事件委派處理模型。在這個事件處理模型裡面,命令對象實現AWT的listener介面,相當於命令介面。為把一個命令對象與一個AWT構件串連起來,需要把它登記成一個事件的listener。構件認識listener介面,而不在乎介面是怎麼實現的。換言之,AWT構件不在意命令所代表實現操作。
三、
命令模式的使用情境
命令模式優缺點
優點:(1)命令模式使新的命令很容易地被加入到系統裡(2)允許接收請求的一方決定是否要否決請求(3)能較容易的設計一個命令隊列(4)可以容易的實現對請求的Undo和Redo(5)在需要的情況下,可以較容易地將命令記入日誌。
適合的情況
1、使用命令模式作為“回調”在物件導向系統中的替代。“回調”講的便是先將一個函數登記上,然後在以後調用此函數。
2、需要在不同的時間指定請求、將請求排隊。一個命令對象和原先的請求發出者可以有不同的生命期。這時命令的接收者可以是在本地,也可以在網路的另外一個地址。
3、系統需要支援命令的撤消。命令對象可以把狀態儲存起來,等到用戶端需要撤消命令所產生的效果時,可以調用undo()方法撤銷。命令對象還可以提供redo()方法,以供用戶端在需要時,再重新實施命令的效果。
4、如果一個系統要將系統中所有的資料更新到日誌裡,以便在系統崩潰時,可以根據日誌裡讀回所有的資料更新命令,重新調用execute()方法一條一條執行這些命令,從而恢複系統在崩潰前所做的資料更新。
5、一人系統需要支援交易(transaction)。一個交易結構封裝了一組資料更新命令。使用命令模式實現交易結構可以使系統增加新的交易類型。
四、
命令模式與其他模式的關係
命令模式與合成模式
合成模式可以應用到命令類的合成上,從幾個具體命令類合成宏命令類。可以在任何需要的時候重新把這些記錄下來的命令一次性執行,這就是所謂的宏命令集功能。
備忘錄模式
如果命令需要撤銷和恢複功能的話,備忘錄模式可以用來儲存關於命令的效果狀態資訊。
五、
Swing庫中的命令撤銷和恢複
Swing在javax.swing.undo庫裡提供了撤銷和恢複的系統化處理方法。javax.swing.undo庫雖然是Swing庫的一部分,但它既可以與Swing構件一起使用,又可以與AWT構件一起使用。
每一個命令或操作在Swing裡都叫做一個編輯(Edit)。每一個可撤銷的命令與操作在Swing裡都叫做一個可撤銷編輯。
(1)介面UndoableEdit。一個類如果需要有撤銷和恢複功能的話,就需要實現UndoableEdit介面。
(2)抽象類別AbstractUndoableEdit是對UndoableEdit介面的最小實現,也是javax.swing.undo庫裡其他類的基類。
(3)介面StateEditable是所有類的可以編輯的類必須實現的介面。
(4)SateEdit類代表一個可編輯類的狀態
(5)UndoManager類負責管理所有的對一個可編輯類的編輯。