命令模式定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持撤销的操作。
通常一个命令对象就是要执行的一个命令操作,实现了共同的接口,一个命令对象通过在特定的接受者上绑定一组动作来封装一个请求。一般命令对象将所要操作的动作和接受者绑定在里面,通过提供给外部一个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