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

命令模式的应用

请求队列、日志请求

相关推荐
学习星球18 小时前
AI Agent 成本工程实战:从 OpenAI Codex 的 8 个“烧 Token“Bug 学起
人工智能·设计模式·微信小程序
AI人工智能+电脑小能手1 天前
大白话说Java设计模式-46-责任链模式(业务实战篇)
java·设计模式·责任链模式·风控校验·servlet filter·spring interceptor·链式处理
码匠许师傅2 天前
【设计模式精讲】7.建造者模式(Builder)
设计模式·建造者模式
码匠许师傅2 天前
【设计模式精讲】6.抽象工厂(Abstract Factory)
c++·设计模式
workflower3 天前
人形机器人灵巧手产业链
人工智能·设计模式·机器人·云计算·无人机
Java后端的Ai之路3 天前
03、Python - 抽象工厂模式
开发语言·python·设计模式·抽象工厂模式·通用智慧
AI人工智能+电脑小能手3 天前
大白话说Java设计模式-45-解释器模式(源码剖析篇)
java·设计模式·解释器模式·源码分析·pattern·spel·javacc
码匠许师傅3 天前
【设计模式精讲】4.单例模式(Singleton)
c++·单例模式·设计模式
雾削木3 天前
2026 编程领域热点知识速览:AI 辅助开发、设计模式实战与嵌入式高效迭代
人工智能·设计模式
AI人工智能+电脑小能手4 天前
大白话说Java设计模式-42-访问者模式(业务实战篇)
java·spring·设计模式·访问者模式·asm·营销规则·数据结构与操作分离