Skip to content

命令模式把"请求"封装成对象,好处是可以排队、记录、撤销。线程池的 Runnable、编辑器的"撤销"就是它的落地。这篇讲清它怎么把"调用"变成"对象"。

一、解决什么问题:把请求变成对象

直接调用是 light.on()——调用完就没了,无法排队、无法撤销、无法记录。

命令模式的思路:把"开灯"这个动作封装成一个命令对象,这个对象可以被存储、排队、撤销。

二、核心结构

java
// 命令接口
interface Command {
    void execute();
    void undo();      // 撤销
}

// 接收者:真正干活的对象
class Light {
    void on() { System.out.println("开灯"); }
    void off() { System.out.println("关灯"); }
}

// 具体命令:封装"开灯"这个动作
class LightOnCommand implements Command {
    private Light light;
    LightOnCommand(Light light) { this.light = light; }
    public void execute() { light.on(); }
    public void undo() { light.off(); }
}

// 调用者:不关心具体命令,只负责触发
class RemoteControl {
    private Command command;
    void setCommand(Command c) { this.command = c; }
    void press() { command.execute(); }
}

// 使用
RemoteControl remote = new RemoteControl();
remote.setCommand(new LightOnCommand(new Light()));
remote.press();   // 开灯

关键:命令把"动作"变成了"对象"——LightOnCommand 可以被存进列表(命令队列)、被记录(日志)、被撤销(undo)。

三、核心价值

  • 解耦:调用者(RemoteControl)不认识接收者(Light),只认识 Command
  • 可排队:命令对象可以进队列,异步执行
  • 可撤销:命令带 undo,支持撤销/重做
  • 可记录:命令可以写日志,崩溃后重放

四、实际应用

  • 线程池Runnable 就是命令对象——你把"要执行的动作"封装成 Runnable,线程池排队执行
  • 编辑器撤销:每个操作是一个命令,撤销 = 逆序执行 undo
  • 菜单/快捷键:菜单项绑定命令对象

小结

  • 命令把"请求"封装成对象,可排队、记录、撤销
  • 调用者、接收者通过命令解耦
  • 典型:线程池 Runnable、编辑器撤销

相关:《策略模式》(命令封装"动作",策略封装"算法",都是行为封装,但命令多一层"撤销/排队")。