Head First Design Patterns - 命令模式

什么是命令模式

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

为什么会有命令模式

假设要设置一个遥控器,遥控器需要控制多个设备,每个设备除了开关,可能还会有属于自己的一些特定的函数,如下图所示:

如果按照常规的设计思路,遥控器中需要包含很多if ... else判断,且每次新增设备,都需要入侵到遥控器内部代码中修改,这是一个糟糕的设计,

命令模式的特点

命令模式能把动作的请求者,从实际执行动作的对象解耦。通过在设计中引入命令对象,把一些事情(像开灯)封装成一个特定对象。

如果按下遥控器,遥控器会请求命令对象去做一些事情,遥控器并不知道实际的工作内容是什么。这就相当于把遥控器和灯解耦了。

当你需要把做出请求的对象,从知道如何执行请求的对象解耦时候,可以使用命令模式。

命令模式的类图

代码案例

  1. Command接口
java 复制代码
public interface Command {
    public void execute();

    public void undo();
}
  1. 设备类
java 复制代码
public class Light {
    private String name;
    public void on() {
        System.out.println("light on");
    }

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

    public Light(String name) {
        this.name = name;
    }
}
  1. 命令对象-关灯
java 复制代码
public class LightOffCommand implements Command{
    Light light;

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

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

    @Override
    public void undo() {
        light.on();
    }
}
  1. 命令对象-开灯
java 复制代码
public class LightOnCommand implements Command {
    Light light;

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

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

    @Override
    public void undo() {
        light.off();
    }
}
  1. 命令对象-空对象
java 复制代码
public class NoCommand implements Command{
    @Override
    public void execute() {

    }

    @Override
    public void undo() {

    }
}

空对象经常在设计模式中用到,可以免除对null的判断

  1. 命令的接受者-相当于遥控器类
java 复制代码
public class RemoteControllerWithUndo {
    Command[] onCommands;
    Command[] offCommands;
    Command undoCommand;

    public RemoteControllerWithUndo() {
        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 setCommands(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();
    }

    @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();
    }
}
  1. 命令的调用者
java 复制代码
public class RemoteLoader {
    public static void main(String[] args) {
        RemoteControllerWithUndo remoteControllerWithUndo = new RemoteControllerWithUndo();

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

        LightOnCommand livingOnCommand = new LightOnCommand(livingRoomLight);
        LightOffCommand lightOffCommand = new LightOffCommand(livingRoomLight);

        remoteControllerWithUndo.setCommands(0, livingOnCommand, lightOffCommand);

        remoteControllerWithUndo.onButtonWasPushed(0);
        remoteControllerWithUndo.offButtonWasPushed(0);

        System.out.println(remoteControllerWithUndo);

        remoteControllerWithUndo.undoButtonWasPushed();
    }
}
  1. 结果

命令模式的应用

请求队列、日志请求

相关推荐
狼哥IKOO1 小时前
AI 终端模拟器 Python 脚本
后端·设计模式·github
jf加菲猫1 小时前
24 设计模式总结
设计模式
wenbin_java7 小时前
设计模式之解释器模式:原理、实现与应用
java·设计模式·解释器模式
-权子-9 小时前
设计模式 - 代理模式Proxy
设计模式·代理模式
StrongerLLL9 小时前
策略模式
设计模式
程序员沉梦听雨10 小时前
适配器模式详解
设计模式·适配器模式
01空间10 小时前
设计模式简述(二)单例模式
设计模式
渊渟岳11 小时前
为什么学习设计模式?
设计模式
程序员JerrySUN17 小时前
设计模式 Day 3:抽象工厂模式(Abstract Factory Pattern)详解
设计模式·抽象工厂模式
程序员沉梦听雨19 小时前
原型模式详解
设计模式·原型模式