其他分享
首页 > 其他分享> > [设计模式] 命令模式

[设计模式] 命令模式

作者:互联网

[设计模式] 命令模式

目录

手机用户请横屏获取最佳阅读体验,REFERENCES中是本文参考的链接,如需要链接和更多资源,可以关注其他博客发布地址。

平台 地址
CSDN https://blog.csdn.net/sinat_28690417
简书 https://www.jianshu.com/u/3032cc862300
个人博客 https://yiyuery.github.io/NoteBooks/

命令模式 将请求封装成对象,这可以让你使用不同的请求、队列或者是日志请求来参数化其他对象。命令模式一般支持定义撤销操作。

命令模式实现

简单命令

首先来让我们实现一个能开灯的遥控命令场景。

在这里插入图片描述

//简单命令接口定义,内部含有一个执行方法
public interface Command {

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

定义一个开灯的命令接口实现:

public class LightOnCommand implements Command {
    /**
     * 执行
     */
    @Override
    public void execute() {
        System.out.println("The light has been turned on!");
    }
}

定义一个遥控器:

@Data
public class SimpleRemoteController {

    /**
     * 命令
     */
    private Command command;

    /**
     * 遥控按钮被按下时,执行命令
     */
    public void buttonWasPressed(){
        command.execute();
    }
}

Ex.1

/**
 * 测试遥控器按下开灯的按钮
 */
@Test
public void testX1(){
    SimpleRemoteController remoteController = new SimpleRemoteController();
    remoteController.setCommand(new LightOnCommand());
    //按键
    remoteController.buttonWasPressed();

    //The light has been turned on!
}

批量命令

如果是需要一组命令的执行呢?

补充定义一个命令NoCommand,用于默认命令的信息打印。

public class NoCommand implements Command {
    /**
     * 执行
     */
    @Override
    public void execute() {
        System.out.println("Command has not been defined!");
    }
}
public class MultipleRemoteController {

    Command[] commands;

    public MultipleRemoteController(int num) {
        commands = new Command[num];
        for (Command command : commands) {
            command = new NoCommand();
        }
    }

    public void setCommand(int index,Command command){
        commands[index] = command;
    }

    /**
     * 遥控按钮被按下时,执行命令
     */
    public void buttonWasPressed(int index){
        commands[index].execute();
    }
}

Ex.2

/**
 * 测试遥控器按下开灯的按钮
 */
@Test
public void testX2(){
    MultipleRemoteController remoteController = new MultipleRemoteController(2);
    remoteController.setCommand(0,new LightOnCommand());
    remoteController.setCommand(1,new TVOnCommand());
    //按键
    remoteController.buttonWasPressed(0);
    remoteController.buttonWasPressed(1);

    //The light has been turned on!
    //TV has been turned on!
}

简单撤销

定义两组命令,每次在执行开启操作前将对应的关闭操作写入缓存变量,在执行撤销方法时,执行即可。

//为了实现代码复用(可以暂时不关注,只关注于宏命令的使用即可),将遥控器的公共部分抽离到一个抽象基类中:
public abstract class AbstractRemoteController<T,K extends Command> {

    protected K undoCommand;

    /**开启操作命令数组*/
    protected K[] onCommands;
    /**关闭操作命令数组*/
    protected K[] offCommands;

    public boolean supportUndo(){
        return true;
    }

    /**
     * 设置命令
     * @param index
     * @param onCommand
     * @param offCommand
     */
    public abstract void setCommand(int index, T onCommand, T offCommand);


    /**
     * 遥控按钮被按下时,执行命令
     */
    public abstract void buttonWasPressed(int index);

    /**
     * 开启操作的撤销按钮
     */
    public  void undoButtonWasPressed(){
        //该基类的定义使用了模版模式,是否支持undo操作由子类决定
        if(supportUndo()){
            undoCommand.execute();
        }
    }
}

//支持简单撤销的遥控器
public class SupportUndoRemoteController extends AbstractRemoteController<Command,Command> {

    public SupportUndoRemoteController(int num) {
        onCommands = new Command[num];
        offCommands = new Command[num];
        for (int i = 0; i < num; i++) {
            onCommands[i] = new NoCommand();
            offCommands[i] = new NoCommand();
        }
    }

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



    /**
     * 遥控按钮被按下时,执行命令
     */
    @Override
    public void buttonWasPressed(int index){
        onCommands[index].execute();
        undoCommand = offCommands[index];
    }

}

Ex.3

/**
 * 支持开启操作的简单撤销
 */
@Test
public void testX3(){
    SupportUndoRemoteController supportUndoRemoteController = new SupportUndoRemoteController(2);

    //设置灯的开和关命令
    supportUndoRemoteController.setCommand(0,new LightOnCommand(),new LightOffCommand());
    //设置电视的开和关命令
    supportUndoRemoteController.setCommand(1,new TVOnCommand(),new TVOffCommand());

    //先开电视后开灯
    supportUndoRemoteController.buttonWasPressed(1);
    supportUndoRemoteController.buttonWasPressed(0);

    //开电视后撤销再开灯
    supportUndoRemoteController.buttonWasPressed(1);
    supportUndoRemoteController.undoButtonWasPressed();
    supportUndoRemoteController.buttonWasPressed(0);

    //TV has been turned on!
    //The light has been turned on!

    //TV has been turned on!
    //TV has been turned off!
    //The light has been turned on!
}

宏命令

定义一组命令的执行,类似于 MicroSoft 常用的宏定义函数一样

假定我们定义一个宏命令实现回家后的一个智能操作:包含开灯和开电视,并要求它支持撤销能力。

//宏命令
public class MacroCommand implements Command {

    Command[] commands;

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

    /**
     * 执行
     */
    @Override
    public void execute() {
        for (Command command : commands) {
            command.execute();
        }
    }
}

//支持宏命令的遥控器
public class SupportMacroRemoteController extends AbstractRemoteController<MacroCommand,Command> {

    public SupportMacroRemoteController(int num) {
        onCommands= new Command[num];
        offCommands = new Command[num];
        for (int i = 0; i <num ; i++) {
            onCommands[i]= new NoCommand();
            offCommands[i]= new NoCommand();
        }
    }

    @Override
    public void setCommand(int index, MacroCommand onMacroCommand, MacroCommand offMacroCommand){
        onCommands[index] = onMacroCommand;
        offCommands[index] = offMacroCommand;
    }

    /**
     * 遥控按钮被按下时,执行命令
     *
     * @param index
     */
    @Override
    public void buttonWasPressed(int index) {
        onCommands[index].execute();
        undoCommand = offCommands[index];
    }

    @Override
    public boolean supportUndo() {
        return true;
    }
}
//开电视
public class TVOnCommand implements Command {
    /**
     * 执行
     */
    @Override
    public void execute() {
        System.out.println("TV has been turned on!");
    }
}

Ex.4

/**
 * 宏命令测试
 */
@Test
public void testX4(){
    SupportMacroRemoteController supportUndoRemoteController = new SupportMacroRemoteController(2);
    Command[] partyOn = new Command[]{new LightOnCommand(),new TVOnCommand()};
    Command[] partyOff = new Command[]{new LightOffCommand(),new TVOffCommand()};
    supportUndoRemoteController.setCommand(0,new MacroCommand(partyOn),new MacroCommand(partyOff));

    //开Party后撤销
    supportUndoRemoteController.buttonWasPressed(0);
    supportUndoRemoteController.undoButtonWasPressed();

    //The light has been turned on!
    //TV has been turned on!
    //The light has been turned off!
    //TV has been turned off!
}

标准撤销方式

针对于命令场景的撤销操作,其实我们可以直接定义一个undo操作接口在Command中,此处考虑到演示的代码结构,我们在补充一个接口继承Command来实现

public interface SupportUndoCommand extends Command {

    /**
     * 撤销操作
     */
    void undo();
}

对应的undo方式执行也调整下实现:

//新的开灯方法
public class LightOnCommand2 implements SupportUndoCommand {
    /**
     * 执行
     */
    @Override
    public void execute() {
        System.out.println("The light has been turned on!");
    }

    /**
     * 撤销操作
     */
    @Override
    public void undo() {
        System.out.println("The light turn on has been canceled!");
    }
}
//新的开电视方法
public class TVOnCommand2 implements SupportUndoCommand {
    /**
     * 执行
     */
    @Override
    public void execute() {
        System.out.println("TV has been turned on!");
    }

    /**
     * 撤销操作
     */
    @Override
    public void undo() {
        System.out.println("TV turn on has been canceled!");
    }
}
//支持undo的遥控器
public class NewSupportUndoRemoteController extends AbstractRemoteController<SupportUndoCommand,SupportUndoCommand> {

    public NewSupportUndoRemoteController(int num) {
        onCommands = new SupportUndoCommand[num];
        for (int i = 0; i < num; i++) {
            onCommands[i] = new NoUndoCommand();
        }
    }

    @Override
    public void setCommand(int index, SupportUndoCommand onCommand, SupportUndoCommand offCommand){
        onCommands[index] = onCommand;
    }



    /**
     * 遥控按钮被按下时,执行命令
     */
    @Override
    public void buttonWasPressed(int index){
        onCommands[index].execute();
    }

    /**
     * 开启操作的撤销按钮
     */
    @Override
    public void undoButtonWasPressed(){
        for (SupportUndoCommand onCommand : onCommands) {
            onCommand.undo();
        }
    }

}

Ex.5

 /**
    * 宏命令 & 标准撤销测试
    */
@Test
public void testX5(){
   
    NewSupportUndoRemoteController newSupportUndoRemoteController = new NewSupportUndoRemoteController(1);
    SupportUndoCommand[] partyOn2 = new SupportUndoCommand[]{new LightOnCommand2(),new TVOnCommand2()};
    SupportUndoCommand[] partyOff2 = new SupportUndoCommand[]{new LightOffCommand2(),new TVOffCommand2()};
    newSupportUndoRemoteController.setCommand(0,new MacroCommand2(partyOn2),new MacroCommand2(partyOff2));

    //开Party后撤销
    newSupportUndoRemoteController.buttonWasPressed(0);
    newSupportUndoRemoteController.undoButtonWasPressed();

    //The light has been turned on!
    //TV has been turned on!
    //The light turn on has been canceled!
    //TV turn on has been canceled!
}

总结

模式特点

敲黑板 !!!!

更多

扫码关注架构探险之道,回复文章标题,获取本文相关源码和资源链接

在这里插入图片描述

知识星球(扫码加入获取历史源码和文章资源链接)

在这里插入图片描述

标签:void,turned,模式,命令,Command,been,new,设计模式,public
来源: https://blog.51cto.com/u_15263565/2886091