天天看點

Java設計模式之指令模式

指令模式定義:将“請求”封裝成對象,以便使用不同的請求、隊列或者日志來參數化其他對象。指令模式也支援撤銷的操作。

通常一個指令對象就是要執行的一個指令操作,實作了共同的接口,一個指令對象通過在特定的接受者上綁定一組動作來封裝一個請求。一般指令對象将所要操作的動作和接受者綁定在裡面,通過提供給外部一個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