概述:
命令模式把發出命令的責任和執行命令的責任分開,委派給不同的對象。
命令模式(Command Pattern):將一個請求封裝為一個對象,從而使我們可用不同的請求對客戶進行參數化;對請求排隊或者記錄請求日志,以及支持可撤銷的操作。命令模式又稱為動作(Action)模式或事務(Transaction)模式。
適用性
1)系統需要將請求調用者和請求接收者解耦,使得調用者和接收者不直接交互。2)系統需要在不同的時間指定請求、將請求排隊和執行請求。3)系統需要支持命令的撤銷(Undo)操作和恢復(Redo)操作。4)系統需要將一組操作組合在一起,即支持宏命令。
抽象命令類(Command): 聲明執行操作的接口。調用接收者相應的操作,以實現執行的方法Execute。具體命令類(ConcreteCommand): 創建一個具體命令對象並設定它的接收者。通常會持有接收者,並調用接收者的功能來完成命令要執行的操作。調用者(Invoker): 要求該命令執行這個請求。通常會持有命令對象,可以持有很多的命令對象。接收者(Receiver): 知道如何實施與執行一個請求相關的操作。任何類都可能作為一個接收者,只要它能夠實現命令要求實現的相應功能。客戶類(Client): 創建具體的命令對象,並且設置命令對象的接收者。真正使用命令的客戶端是從Invoker來觸發執行。
Command模式優點:
1) 降低系統的耦合度:Command模式將調用操作的對象與知道如何實現該操作的對象解耦。
2) Command是頭等的對象。它們可像其他的對象一樣被操縱和擴展。
3) 組合命令:你可將多個命令裝配成一個組合命令,即可以比較容易地設計一個命令隊列和宏命令。一般說來,組合命令是Composite模式的一個實例。
4) 增加新的Command很容易,因為這無需改變已有的類。
5)可以方便地實現對請求的Undo和Redo。
命令模式的缺點: 使用命令模式可能會導致某些系統有過多的具體命令類。因為針對每一個命令都需要設計一個具體命令類,因此某些系統可能需要大量具體命令類,這將影響命令模式的使用電視機遙控器 :
電視機是請求的接收者,
遙控器是請求的發送者,
遙控器上有一些按鈕,不同的按鈕對應電視機的不同操作。抽象命令角色由一個命令接口來扮演,
有三個具體的命令類實現了抽象命令接口,這三個具體命令類分別代表三種操作:打開電視機、關閉電視機和切換頻道。
顯然,電視機遙控器就是一個典型的命令模式應用實例public class Client { public static void main(String[] args) { TV tv = new TV(); OpenCammand op = new OpenCammand(tv); InvokerControler ic = new InvokerControler(op); ic.action(); } } interface Command { void execute(); } class OpenCammand implements Command{ TV tv; public OpenCammand(TV tv) { this.tv = tv; } @Override public void execute() { // TODO Auto-generated method stub tv.open(); } } class CloseCammand implements Command{ TV tv; public CloseCammand(TV tv) { this.tv = tv; } @Override public void execute() { // TODO Auto-generated method stub tv.close(); } } class changeChanlCammand implements Command{ TV tv; public changeChanlCammand(TV tv) { this.tv = tv; } @Override public void execute() { // TODO Auto-generated method stub tv.change(); } } class TV{ void open() { System.out.println("open tv"); } void close() { System.out.println("close tv"); } void change() { System.out.println("change tv"); } } class InvokerControler{ Command command; public InvokerControler(Command c) { command = c; } void action() { command.execute(); } }