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. 结果

命令模式的应用

请求队列、日志请求

相关推荐
wrx繁星点点1 小时前
状态模式(State Pattern)详解
java·开发语言·ui·设计模式·状态模式
金池尽干3 小时前
设计模式之——观察者模式
观察者模式·设计模式
也无晴也无风雨3 小时前
代码中的设计模式-策略模式
设计模式·bash·策略模式
捕鲸叉12 小时前
MVC(Model-View-Controller)模式概述
开发语言·c++·设计模式
wrx繁星点点13 小时前
享元模式:高效管理共享对象的设计模式
java·开发语言·spring·设计模式·maven·intellij-idea·享元模式
凉辰13 小时前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
菜菜-plus13 小时前
java设计模式之策略模式
java·设计模式·策略模式
暗黑起源喵13 小时前
设计模式-迭代器
设计模式
lexusv8ls600h14 小时前
微服务设计模式 - 网关路由模式(Gateway Routing Pattern)
spring boot·微服务·设计模式
sniper_fandc17 小时前
抽象工厂模式
java·设计模式·抽象工厂模式