23种设计模式之命令模式

遥控器案例,控制灯开或关,音响音量大小,设置CD

1、把命令封装成接口,不同设备继承接口实现功能;

如上图,灯的开、关和音响开、关、调音量、设置CD功能类定义好,其相应功能的执行命令封装成接口,Control通过命令接口的方法实现对应功能; 

public class Light {

    String loc="";//灯位置,如卧室,客厅

    public Light(String loc){
        this.loc=loc;
    }

    public void on(){
        System.out.println(loc+" On");
    }

    public void off(){
        System.out.println(loc+" Off");
    }

}
Light 灯功能类
public class Stereo {

    static int volume=0;

    public void on(){
        System.out.println("Stereo On");
    }

    public void off(){
        System.out.println("Stereo Off");
    }

    public void setCD(){
        System.out.println("Stereo setCD");
    }

    public void setVol(int vol){
        this.volume=vol;
        System.out.println("Stereo volume="+volume);
    }

    public int getVol(){
        return volume;
    }

    public void start(){
        System.out.println("Stereo Start");
    }

}
Stereo 音响功能类
public interface Command {

    public void execute();

    public void undo();

}
Command 命令接口

单独的功能,如灯的开、关和音响的开、关、调大音量、调小音量,实现命令接口

public class LightOnCommand implements Command {

    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

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

    public void undo() {
        light.off();
    }
}
LightOnCommand implements Command开灯功能
public class LightOffCommand implements Command {

    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

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

    public void undo() {
        light.on();
    }
}
LightOffCommand implements Command关灯功能
public class StereoOnCommand implements Command {

    private Stereo stereo;

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

    public void execute() {
        //可以多个命令同时执行
        stereo.on();
        stereo.setCD();
    }

    public void undo() {
        stereo.off();
    }
}
StereoOnCommand implements Command开音响功能
public class StereoOffCommand implements Command {

    private Stereo stereo;

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

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

    public void undo() {
        stereo.on();
    }
}
StereoOffCommand implements Command关音响功能
public class StereoAddVolCommand implements Command {

    private Stereo stereo;

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

    public void execute() {
        int vol = stereo.getVol();
        if (vol < 11) {
            stereo.setVol(++vol);
        }
    }

    public void undo() {
        int vol = stereo.getVol();
        if (vol > 0) {
            stereo.setVol(--vol);
        }
    }
}
StereoAddVolCommand implements Command调大音量功能
public class StereoSubVolCommand implements Command {

    private Stereo stereo;

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

    public void execute() {
        int vol = stereo.getVol();
        if (vol > 0) {
            stereo.setVol(--vol);
        }
    }

    public void undo() {
        int vol = stereo.getVol();
        if (vol < 11) {
            stereo.setVol(++vol);
        }
    }
}
StereoSubVolCommand implements Command调小音量功能

NoCommand类,用来初始化命令控制器上按钮,内部实现命令接口,但不执行功能,就类似按按钮不起作用

public class NoCommand implements Command {
    public void execute() {

    }

    public void undo() {

    }
}
NoCommand implements Command

遥控器接口,遥控器通过控制每一排的开、关按钮来让相应的功能命令执行

public interface Control {

    //slot位置,即打开或关闭哪排按钮

    void onButton(int slot);

    void offButton(int slot);

    void undoButton();

    void setCommand(int slot, Command onCommand, Command offCommand);

}
Control 遥控器接口
public class CommandModeControl implements Control {

    private Command[] onCommands;
    private Command[] offCommands;
    private Stack<Command> stack=new Stack<Command>();

    public CommandModeControl() {
        onCommands = new Command[5];
        offCommands = new Command[5];

        Command noCommand = new NoCommand();

        for (int i = 0; i < onCommands.length; i++) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
    }

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

    public void onButton(int slot) {
        onCommands[slot].execute();
        stack.push(onCommands[slot]);
    }

    public void offButton(int slot) {
        offCommands[slot].execute();
        stack.push(offCommands[slot]);
    }

    public void undoButton() {
        stack.pop().undo();
    }
}
CommandModeControl implements Control遥控器接口实现,初始化设置每排开、关按钮命令为nocommand,setCommand方法设置某排控制灯或音响功能,其中onCommand和offCommand数组表示两排开关按钮

 下面再添加一同时控制多个功能的命令

public class MarcoCommand implements Command {

    private Command[] commands;

    public MarcoCommand(Command[] commands){
        this.commands=commands;
    }

    public void execute() {
        for (int i = 0; i < commands.length; i++) {
            commands[i].execute();
        }
    }

    public void undo() {
        for (int i = 0; i < commands.length; i++) {
            commands[i].undo();
        }
    }
}
MarcoCommand implements Command通过传入命令数组,数组中的命令同时执行

遥控器操作设备,也就是Control中的onButton、offButton调用Command的execute方法,undoButton执行Command的undo方法

设备功能实现Command接口,各自实现不同,而Command接口对外暴露的只有相同的方法

public class ControlTest {

    public static void main(String[] args){
        Control control=new CommandModeControl();
        Light bedroomLight=new Light("BedRoom");
        Light kitchLight=new Light("Kitch");
        Stereo stereo=new Stereo();

        Command bedroomLightOn=new LightOnCommand(bedroomLight);
        Command bedroomLightOff=new LightOffCommand(bedroomLight);
        Command kitchLightOn=new LightOnCommand(kitchLight);
        Command kitchLightOff=new LightOffCommand(kitchLight);

        //同时开、关两个灯
        Command[] onCommands={bedroomLightOn,kitchLightOn};
        Command[] offCommands={bedroomLightOff,kitchLightOff};
        Command marcoCommandOn=new MarcoCommand(onCommands);
        Command marcoCommandOff=new MarcoCommand(offCommands);

        Command stereoOn=new StereoOnCommand(stereo);
        Command stereoOff=new StereoOffCommand(stereo);
        Command stereoAddVol=new StereoAddVolCommand(stereo);
        Command stereoSubVol=new StereoSubVolCommand(stereo);

        control.setCommand(0,bedroomLightOn,bedroomLightOff);
        control.setCommand(1,kitchLightOn,kitchLightOff);
        control.setCommand(2,stereoOn,stereoOff);
        control.setCommand(3,stereoAddVol,stereoSubVol);
        control.setCommand(4,marcoCommandOn,marcoCommandOff);

        control.onButton(0);
        control.offButton(0);
        control.onButton(1);
        control.offButton(1);
        control.onButton(2);
        control.offButton(2);
        control.onButton(3);
        control.offButton(3);
        System.out.println("~~~~~~~~~~~~~");
        control.onButton(4);
        control.offButton(4);
    }

}
测试代码

解耦后,设备升级或添加新设备,都不会影响其他设备代码

原文地址:https://www.cnblogs.com/hujiapeng/p/8145677.html