命令模式:

将 “请求” 封装成对象,以便使用不同的请求、队列或者日志来参与参数化其他对象。命令模式也支持可撤销的操作。

  1. 命令模式将发出请求的对象和执行请求的对象解耦。
  2. 在被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者和一个或一组动作。
  3. 调用者通过调用命令对象的execute()发出请求,这会使得接收者的动作被调用。
  4. 调用者可以接受命令当作参数,甚至在运行时动态地进行。
  5. 命令可以支持撤销,做法是实现一个undo()方法来回到execute()被执行前的状态。
  6. 宏命令是命令的一种简单的延续,允许调用多个命令。宏方法也可以支持撤销。
  7. 实际操作时,很常见使用“聪明”命令对象,也就直接实现了请求,而不是将工作委托给接收者。
  8. 命令也可以用来实现日志和事务系统。

设计模式-命令模式_i++

/**
 * @Description: 命令模式-命令接口
 * @date 2018/4/9 22:54
 */
public interface Command {

    /**
     * 执行
     */
     void execute();

    /**
     * 撤销
     */
    void undo();
}
public class Light {

    public Light(String weizhi) {
        System.out.println("位置 = [" + weizhi + "]");
    }

    public void on(){
        System.out.println(".....打开");
    }

    public void off(){
        System.out.println("..........关闭");
    }
}
public class LightOffCommand  implements Command{

    Light light;

    /**
     * 构造器传入了某个电灯,以便让这个命令控制,然后记录在实例变量中。
     * 一旦调用execute(),就由这个电灯对象成为接收者,负责接收请求。
     * @param light
     */
    public LightOffCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.off();
    }

    public void undo() {
        light.on();
    }
}
public class LightOnCommand implements Command{

    Light light;

    /**
     * 构造器传入了某个电灯,以便让这个命令控制,然后记录在实例变量中。
     * 一旦调用execute(),就由这个电灯对象成为接收者,负责接收请求。
     * @param light
     */
    public LightOnCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.on();
    }

    public void undo() {
        light.off();
    }
}
public class StereoOffCommand implements Command{

    Stereo stereo;

    public StereoOffCommand(Stereo stereo) {
        this.stereo = stereo;
    }

    public void execute() {
        stereo.off();
    }

    public void undo() {

    }
}
public class StereoOnWithCDCommand implements Command{
    Stereo stereo;

    public StereoOnWithCDCommand(Stereo stereo) {
        this.stereo = stereo;
    }

    /**
     * 执行后会调用3个方法
     * 打开、播放cd、音量调到11
     */
    public void execute() {
        stereo.on();
        stereo.setCd();
        stereo.setVolume(11);
    }

    public void undo() {

    }
}
/**
 * @Description: 空对象,当你不想返回一个有意义的对象时,空对象很有用。
 * @date 2018/4/10 20:45
 */
public  class NoCommand implements Command{
    public void execute() {

    }

    public void undo() {

    }
}
public class RemoteControl {

    //遥控器处理7个开与关的命令,使用相应的数组记录命令
    Command[] onCommands;
    Command[] offCommands;
    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;
    }

    /**
     * 这些命令将记录在开关数组中对应的插槽位置,以供稍后使用
     * @param slot 位置
     * @param onCommand 开的命令
     * @param offCommand 关的命令
     */
    public void setCommand(int slot,Command onCommand,Command offCommand){
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }

    /**
     * 按下开按钮就会调用相应的方法
     * @param slot
     */
    public void onButtonWasPushed(int slot){
        onCommands[slot].execute();
        undoCommand = onCommands[slot];
    }

    /**
     * 按下关按钮就会调用相应的方法
     * @param slot
     */
    public void offButtonWasPushed(int slot){
        offCommands[slot].execute();
        undoCommand = offCommands[slot];
    }

    /**
     * 撤销按钮
     */
    public void undoButtonWasPushed(){
        undoCommand.undo();
    }

    @Override
    public String toString() {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("\n--------Remote Control -----------\n");
        for (int i = 0; i < onCommands.length; i++) {
            stringBuffer.append("[slot"+i+"]"+onCommands[i].getClass().getName()+"  "+offCommands[i].getClass().getName()+"\n");
        }
        return stringBuffer.toString();
    }
}
public class SimpleRemoteControl {
    Command slot;

    public SimpleRemoteControl() {}

    public void setCommand(Command command){
        slot = command;
    }

    public void buttonWasPressed(){
        slot.execute();
    }
}
public class Test {
    public static void main(String[] args) {
        RemoteControl remoteControl = new RemoteControl();

        Light livingRoomLight = new Light("Living Room");

        LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);

        LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);

        remoteControl.setCommand(0,livingRoomLightOn,livingRoomLightOff);

        remoteControl.onButtonWasPushed(0);
        remoteControl.offButtonWasPushed(0);
        remoteControl.undoButtonWasPushed();

        System.out.println("--------------------------------");

        remoteControl.offButtonWasPushed(0);
        remoteControl.onButtonWasPushed(0);
        remoteControl.undoButtonWasPushed();

    }
}
public class Test2 {
    public static void main(String[] args) {
        RemoteControl remoteControl = new RemoteControl();

        //装置创建在合适的位置
        Light livingRoomLight = new Light("Living Room");
        Light kitchenLight = new Light("Kitchen");

        Stereo stereo = new Stereo("Living Room");

        //创建所有的电灯命令对象
        LightOnCommand livingRoomLightOn = new LightOnCommand(livingRoomLight);
        LightOffCommand livingRoomLightOff = new LightOffCommand(livingRoomLight);
        LightOnCommand kitchenLightOn = new LightOnCommand(kitchenLight);
        LightOffCommand kitchenLightOff = new LightOffCommand(kitchenLight);

        //创建音响的开与关命令
        StereoOnWithCDCommand stereoOnWithCDCommand = new StereoOnWithCDCommand(stereo);
        StereoOffCommand stereoOffCommand = new StereoOffCommand(stereo);

        //加载到遥控器插槽中去
        remoteControl.setCommand(0,livingRoomLightOn,livingRoomLightOff);
        remoteControl.setCommand(1,kitchenLightOn,kitchenLightOff);
        remoteControl.setCommand(1,stereoOnWithCDCommand,stereoOffCommand);

        System.out.println(remoteControl);

        remoteControl.onButtonWasPushed(0);
        remoteControl.offButtonWasPushed(0);

        remoteControl.onButtonWasPushed(1);
        remoteControl.offButtonWasPushed(1);

        remoteControl.onButtonWasPushed(2);
        remoteControl.offButtonWasPushed(2);

    }
}
public class Stereo {
    public Stereo(String weizhi) {
        System.out.println("位置 = [" + weizhi + "]");
    }

    public void on(){
        System.out.println(".........打开dvd");
    }

    public void off(){ System.out.println(".........关闭dvd");}
    public void setCd(){}
    public void setDvd(){}
    public void setRadio(){}
    public void setVolume(int num){System.out.println(".........调音量:"+num);}


}

设计模式-命令模式_插槽_02

设计模式-命令模式_java-命令模式_03