命令模式

1、命令模式的动机

动机:将请求者和接受者进行解耦,发送者与接受者没有直接的引用关系,发送者只需要知道如何发送请求,而不必关注 有那个接受者来执行请求;

2、命令模式的定义

命令模式将”请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象,命令模式支持可撤销的操作。
请求即是命令,命令中封装了动作和接受者,对外之暴露execute()执行方法。

3、命令模式的类结构图

image

分析如下:

4、优缺点和适用场景

优点:

缺点:

适用场景:

5、实例

例:设计一个遥控器,既可以控制电扇,电灯的打开关闭,也可以撤销之前的命令,以及统一操作;

类图:
image

命令接口:

public interface Command {
    void excute();

    void undo();
}

电灯接口及实现:

public interface Light {
    void off();

    void on();
}

public class DropLight implements Light {
    public void off() {
        System.out.println("关掉吊灯");
    }

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

电扇接口及实现:

public interface Fan {
    void off();

    void on();
}

public class DropFan implements Fan {

    public void off() {
        System.out.println("关闭吊扇");
    }

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

具体命令:

@AllArgsConstructor
public class OffFanCommand implements Command {

    private Fan fan;

    public void excute() {
        fan.off();
    }

    public void undo() {
        fan.on();
    }
}

@AllArgsConstructor
public class OnFanCommand implements Command {

    private Fan fan;

    public void excute() {
        fan.on();
    }

    public void undo() {
        fan.off();
    }
}

@AllArgsConstructor
public class OffLightCommand implements Command {
    private Light light;

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

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


@AllArgsConstructor
public class OnLightCommand implements Command {

    Light light;

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

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


public class UnifyCommand implements Command {
    List<Command> commands = new ArrayList<Command>();

    public void setCommand(Command command) {
        commands.add(command);
    }
    public void excute() {
        for(Command command : commands) {
            command.excute();
        }
    }

    public void undo() {
        for(Command command : commands) {
            command.undo();
        }
    }
}

调用者类即遥控器类:

public class RemoteControl {
    private Command[] onCommands;
    private Command[] offCommands;

    private Command preCommand;

    public RemoteControl() {
        onCommands = new Command[3];
        offCommands = new Command[3];
        for(Command command : offCommands) {
            command = new NoCommand();
        }
        for(Command command : onCommands) {
            command = new NoCommand();
        }
    }

    public void setCommands(int i, Command offCommand, Command onCommand) {
        onCommands[i] = onCommand;
        offCommands[i] = offCommand;
    }

    public void offLightButton() {
        offCommands[0].excute();
        preCommand=offCommands[0];
    }

    public void onLightButton() {
        onCommands[0].excute();
        preCommand = onCommands[0];
    }

    public void offFanButton() {
        offCommands[1].excute();
        preCommand = offCommands[1];
    }

    public void onFanButton() {
        onCommands[1].excute();
        preCommand = onCommands[1];
    }

    public void unifyOnButton() {
        onCommands[2].excute();
        preCommand = onCommands[2];
    }

    public void unifyOffButton() {
        offCommands[2].excute();
        preCommand = offCommands[2];
    }

    public void revocation() {
        preCommand.undo();
    }

}

客户端类,test:

public class Test {
    public static void main(String[] args) {
        RemoteControl control = new RemoteControl();
        Light light = new DropLight();
        Fan fan = new DropFan();
        // 设置电灯控制命令
        control.setCommands(0,new OffLightCommand(light),new OnLightCommand(light));
        // 设置电扇控制命令
        control.setCommands(1, new OffFanCommand(fan), new OnFanCommand(fan));
        // 设置统一命令
        UnifyCommand onUnifyCommand = new UnifyCommand();
        onUnifyCommand.setCommand(new OnLightCommand(light));
        onUnifyCommand.setCommand(new OnFanCommand(fan));
        UnifyCommand offUnifyCommand2 = new UnifyCommand();
        offUnifyCommand2.setCommand(new OffLightCommand(light));
        offUnifyCommand2.setCommand(new OffFanCommand(fan));
        control.setCommands(2, offUnifyCommand2, onUnifyCommand);

        //打开电灯
        control.onLightButton();
        //打开电扇
        control.onFanButton();
        //同时关闭电灯电扇
        control.unifyOffButton();
        //撤销上次动作
        control.revocation();

    }
}