CHARLIE SAYS

查理如是说
DATE 2026-08-24
THEME
SERIES / DESIGN_PATTERNS / P-111 · 设计模式

设计模式 017:命令模式(Command)

命令模式(Command pattern)将”请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象,命令模式也支持可撤销的操作。调用者持有的只是命令抽象,不关心命令最终由谁、如何执行。

意图

将命令封装成对象中,以便使用命令来参数化其它对象,或者将命令对象放入队列中进行排队,或者将命令对象的操作记录到日志中,以及支持可撤销的操作。

类图

命令模式有四个角色:

  • Command:命令
  • Receiver:命令接收者,也就是命令真正的执行者
  • Invoker:通过它来调用命令
  • Client:可以设置命令与命令的接收者

原文图片丢失,据文字重绘。

classDiagram
    class Command {
        <<interface>>
        +execute()
    }
    class LightOnCommand {
        -Light light
        +execute()
    }
    class LightOffCommand {
        -Light light
        +execute()
    }
    class Light {
        +on()
        +off()
    }
    class Invoker {
        -Command[] onCommands
        -Command[] offCommands
        +setOnCommand(Command, int)
        +setOffCommand(Command, int)
        +onButtonWasPushed(int)
        +offButtonWasPushed(int)
    }
    class Client
    Command <|.. LightOnCommand
    Command <|.. LightOffCommand
    LightOnCommand --> Light
    LightOffCommand --> Light
    Invoker o-- Command
    Client ..> Invoker
    Client ..> Command
    Client ..> Light

实现

设计一个遥控器,可以控制电灯开关。

命令接口:

public interface Command {
    void execute();
}

两个具体命令,分别封装”开灯”和”关灯”请求:

public class LightOnCommand implements Command {

    Light light;

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

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

public class LightOffCommand implements Command {

    Light light;

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

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

接收者,命令真正的执行者:

public class Light {

    public void on() {
        System.out.println("Light is on!");
    }

    public void off() {
        System.out.println("Light is off!");
    }
}

遥控器(Invoker),只依赖 Command 抽象:

/**
 * 遥控器
 */
public class Invoker {

    private Command[] onCommands;
    private Command[] offCommands;
    private final int slotNum = 7;

    public Invoker() {
        this.onCommands = new Command[slotNum];
        this.offCommands = new Command[slotNum];
    }

    public void setOnCommand(Command command, int slot) {
        onCommands[slot] = command;
    }

    public void setOffCommand(Command command, int slot) {
        offCommands[slot] = command;
    }

    public void onButtonWasPushed(int slot) {
        onCommands[slot].execute();
    }

    public void offButtonWasPushed(int slot) {
        offCommands[slot].execute();
    }
}
public class Client {

    public static void main(String[] args) {
        Invoker invoker = new Invoker();
        Light light = new Light();
        Command lightOnCommand = new LightOnCommand(light);
        Command lightOffCommand = new LightOffCommand(light);
        invoker.setOnCommand(lightOnCommand, 0);
        invoker.setOffCommand(lightOffCommand, 0);
        invoker.onButtonWasPushed(0);
        invoker.offButtonWasPushed(0);
    }
}

JDK 中的应用

  • java.lang.Runnable
  • Netflix Hystrix
  • javax.swing.Action

系列导航

← Angular 22+ 教程 17:Angular 组件 vs Shadow DOM 与样式隔离 目录 软件工程 017:常见企业级代码规范 →
← 返回文章列表