模式定义
将“请求”封装成对象,以便使用不同的请求队列或者日志来参数化其他对象。命令模式也支持可撤销的操作
模式类图
示例
遥控器上不同开关控制不同的电器的开关示例,强耦合设计思路遥控器控制类中判断不同开关然后调用不同的电器。这样设计不利于后期的扩展和维护,需要进行解除耦合的操作。当开关按下时其实遥控器不关心这个开关绑定的是什么电器,只是开关是开我就调用绑定好的电器的开的操作。所以封装所有电器的开,关,撤销等到不同命令中,遥控器上可以根据需要绑定不同电器的操作命令。当开关开或者关的时候,只要调用绑定好的电器的不同命令即可。
/**
* 灯具厂商
*
* @author Colin
* @create 2018-05-02
**/
public class Light {
private String name;
public Light(String name){
this.name=name;
}
public void on(){
System.out.println(this.name+"开灯");
}
public void off(){
System.out.println(this.name+"关灯");
}
}
/**
* 命令接口
*
* @author Colin
* @create 2018-05-02
**/
public interface Command {
/**
* 执行命令
*/
public void execute();
/**
* 撤销
*/
public void undo();
}
/**
* 关灯命令
*
* @author Colin
* @create 2018-05-02
**/
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light){
this.light=light;
}
@Override
public void execute() {
light.off();
}
@Override
public void undo() {
light.on();
}
}
/**
* 开灯命令
*
* @author Colin
* @create 2018-05-02
**/
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light){
this.light=light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
/**
* 空命令
*
* @author Colin
* @create 2018-05-02
**/
public class NoCommand implements Command {
@Override
public void execute() {
}
@Override
public void undo() {
}
}
遥控器,即调用者Invoker
/**
* 遥控器实现类
*
* @author Colin
* @create 2018-05-02
**/
public class RemoteControl {
private Command[] onCommands;
private Command[] offCommands;
private Command undoCommand;
public RemoteControl(){
onCommands=new Command[7];
offCommands=new Command[7];
Command noCommand=new NoCommand();
for (int i=0;i<7;i++){
onCommands[i]=noCommand;
offCommands[i]=noCommand;
}
undoCommand=noCommand;
}
public void setCommand(int slot,Command onCommand,Command offCommand){
onCommands[slot]=onCommand;
offCommands[slot]=offCommand;
}
public void onButtonWasPushed(int slot){
onCommands[slot].execute();
undoCommand=onCommands[slot];
}
public void offButtonWasPushed(int slot){
offCommands[slot].execute();
undoCommand=offCommands[slot];
}
public void undoButtonWasPushed(){
undoCommand.undo();
}
}
客户端,client,动态绑定,解耦
/**
* 遥控器测试类
*
* @author Colin
* @create 2018-05-02
**/
public class RemoteLoader {
@Test
public void testRemoteControl(){
Light livingLight=new Light("卧室");
Light kitchenLight=new Light("厨房");
LightOnCommand livingRoomLightOnCommand=new LightOnCommand(livingLight);
LightOffCommand livingRoomLightOffCommand=new LightOffCommand(livingLight);
LightOnCommand kitchenLightOnCommand=new LightOnCommand(kitchenLight);
LightOffCommand kitchenLightOffCommand=new LightOffCommand(kitchenLight);
RemoteControl remoteControl=new RemoteControl();
remoteControl.setCommand(0,livingRoomLightOnCommand,livingRoomLightOffCommand);
remoteControl.setCommand(1,kitchenLightOnCommand,kitchenLightOffCommand);
remoteControl.onButtonWasPushed(0);
remoteControl.offButtonWasPushed(0);
remoteControl.onButtonWasPushed(1);
remoteControl.offButtonWasPushed(1);
remoteControl.undoButtonWasPushed();
}
}
总结
- 命令模式将发出请求的对象和执行请求的对象解耦,即上面client(请求对象)和Light(执行请求对象)
- 在被解耦的两者之间是通过命令对象进行沟通的,命令对象封装了接收者的一个或者一组动作,即上面的Commd对象,开灯命令和关灯命令
- 调用者通过命令对象的统一的execute方法发出请求,使接受则的动作得以执行