指令模式定義:将“請求”封裝成對象,以便使用不同的請求、隊列或者日志來參數化其他對象。指令模式也支援撤銷的操作。
通常一個指令對象就是要執行的一個指令操作,實作了共同的接口,一個指令對象通過在特定的接受者上綁定一組動作來封裝一個請求。一般指令對象将所要操作的動作和接受者綁定在裡面,通過提供給外部一個execute()方法來觸發所需要的操作。
指令模式實作了“指令的調用者”和“指令的接受者”之間的解耦,由于指令對象裡面已經綁定了所要操作的接受者以及動作,而調用者隻管負責調用相應的指令對象來完成指令所包含的動作,調用者根本不知道它所操作的是哪一個接受者,隻知道它要做的是何種操作而已。
其實指令模式如同其他設計模式一樣——通過将你的的請求和你的處理之間,加上了一個中間人的角色,來達到分離耦合的目的。通過對中間人角色的特殊設計來形成不同的模式。當然指令模式就是一種特殊設計的結果。
它的類圖如下:
通常它的組成包括如下:
1) 指令角色(Command):聲明執行操作的接口。由接口或者抽象類來實作。
2) 具體指令角色(Concrete Command):将一個接收者對象綁定于一個動作,調用接收者相應的操作,以實作指令角色聲明的執行操作的接口。
3) 客戶角色(Client):建立一個具體指令對象(并可以設定它的接收者)。
4) 調用者角色(Invoker):調用指令對象執行這個請求。
5) 接收者角色(Receiver):知道如何實施與執行一個請求相關的操作。任何類都可能作為一個接收者。
一般來說具體指令角色僅僅包含着一種指令,如果想要一個指令包含多種指令那麼就可以利用宏指令,在一個具體指令角色中提前設定好各種具體指令角色來處理。
指令模式一般具有撤銷操作,一般就是在調用者裡面做好預處理,在每一個具體指令角色中設定好撤銷操作的執行動作。
指令模式的優點:
1) 指令模式将調用操作的請求對象與執行該操作的接收對象解耦。
2) 具體指令角色可以被不同的請求者角色重用。
3) 可将多個指令裝配成一個複合指令,即宏指令。
4) 增加新的具體指令角色很容易,因為這無需改變已有的類。
指令模式的應用場景:
1) 需要抽象出待執行的動作,然後以參數的形式提供出來——類似于過程設計中的回調機制。而指令模式正是回調機制的一個面向對象的替代品。
2) 在不同的時刻指定、排列和執行請求。
3) 需要支援取消操作。
4) 支援修改日志功能。這樣當系統崩潰時,這些修改可以被重做一遍。
5) 需要支援事務操作。
指令模式的要點:
1)在被解耦的兩者之間即接受者和調用者通過指令對象來溝通的。
2)調用者通過調用指令對象的execute()送出請求,這就會促使接受者開始執行指令的動作。
舉例說明:
一個控制器,可以控制許多個裝置,通過向裝置發出各種指令來執行。
指令角色接口:
package com.whut.command;
//各種指令的基類
publicinterface Command {
void execute();
void undo();
}
具體指令角色:
publicclass LightOffCommand implements Command {
Light light;
public LightOffCommand(Light light)
{
this.light=light;
@Override
publicvoid execute() {
// TODO Auto-generated method stub
light.off();
publicvoid undo() {
light.on();
調用者角色:
publicclass RemoteControl {
private Command[] onCommands;
private Command[] offCommands;
private Command undoCommand;
public RemoteControl()
onCommands=new Command[7];
offCommands=new Command[7];
undoCommand=new NoCommand();
for(int i=0;i<7;i++)
onCommands[i]=new NoCommand();
offCommands[i]=new NoCommand();
publicvoid setCommand(int slot,Command onCommand,Command offCommand)
onCommands[slot]=onCommand;
offCommands[slot]=offCommand;
publicvoid onButtonWasPressed(int slot)
onCommands[slot].execute();
undoCommand=onCommands[slot];
publicvoid offButtonWasPressed(int slot)
offCommands[slot].execute();
undoCommand=offCommands[slot];
publicvoid undoButtonWasPressed()
undoCommand.undo();
public String toString()
StringBuffer stringBuff=new StringBuffer();
stringBuff.append("\n------Remote Control-------------\n");
stringBuff.append("[slot "+i+" ]"+onCommands[i].getClass().getName()
+" "+offCommands[i].getClass().getName()+"\n");
return stringBuff.toString();
接受者角色:
//各種接受者
publicclass Light {
private String lightType;
public Light(String light)
this.lightType=light;
publicvoid on()
System.out.println("The "+lightType+" is on...");
publicvoid off()
System.out.println("The "+lightType+" is off...");
客戶角色:
publicclass RemoteLoader {
publicstaticvoid main(String[] args)
RemoteControl remote=new RemoteControl();
Light livingRoomLight=new Light("Living Room");
LightOnCommand livingRoomOn=new LightOnCommand(livingRoomLight);
LightOffCommand livingRoomOff=new LightOffCommand(livingRoomLight);
remote.setCommand(0, livingRoomOn, livingRoomOff);
remote.onButtonWasPressed(0);
remote.offButtonWasPressed(0);
System.out.println(remote);
remote.undoButtonWasPressed();
本文轉自 zhao_xiao_long 51CTO部落格,原文連結:http://blog.51cto.com/computerdragon/1156583