《命令模式》|设计模式系列第15篇
系列:行为型模式 · 命令模式(Command Pattern)
关键词:请求封装、命令对象、调用者、接收者、撤销操作、任务队列
一、什么是命令模式
命令模式(Command Pattern):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
属于行为型设计模式。

简单理解:
把请求动作单独封装成命令对象。调用者只需要发起命令,不需要知道命令具体由谁执行、怎么执行。命令对象内部持有接收者,由接收者执行真实业务。可以把命令存入队列、日志,或者实现 undo/redo 撤销重做。
例子:遥控器,每一个按键就是一条命令。按下按键(调用者),触发命令对象,命令去控制家电(接收者)。
核心意图
将请求封装成对象,实现请求与执行方解耦;支持命令排队、日志记录、撤销重做。
适用场景
- 需要将请求调用者和请求接收者解耦
- 需要对请求做排队、延迟执行、任务调度
- 需要支持撤销(undo)、重做(redo)操作
- 需要记录请求日志,方便故障恢复
- 宏命令:一次性批量执行一组命令
⚠️ 缺点预警:每一个动作都要创建一个命令类,会产生大量命令子类,增加代码复杂度。
二、UML结构图
角色划分:
- Command(抽象命令):声明执行接口 execute(),可选增加 undo()
- ConcreteCommand(具体命令):实现Command,持有接收者引用,调用接收者方法
- Invoker(调用者):持有命令对象,触发命令执行,不关心执行细节
- Receiver(接收者):真正执行业务逻辑的对象
- Client(客户端):创建命令对象,绑定接收者,设置到调用者

三、Java 完整示例
场景:RemoteControl 遥控器,控制 Light 灯,支持 turn on / turn off。
代码全部使用英文。
1. Command 抽象命令
public interface Command {
void execute();
void undo();
}
2. Receiver 接收者
public class Light {
public void turnOn() {
System.out.println("Light is turned on");
}
public void turnOff() {
System.out.println("Light is turned off");
}
}
3. ConcreteCommand 具体命令
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
@Override
public void undo() {
light.turnOff();
}
}
public class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
@Override
public void undo() {
light.turnOn();
}
}
4. Invoker 调用者
public class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}
5. Client 客户端
public class Client {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();
remote.pressUndo();
remote.setCommand(lightOff);
remote.pressButton();
remote.pressUndo();
}
}
运行输出:
Light is turned on
Light is turned off
Light is turned off
Light is turned on
四、优缺点总结
✅ 优点
- 解耦调用者与接收者,调用者不需要知道接收者细节
- 命令对象独立,可以排队、持久化、日志记录
- 方便实现 undo / redo 撤销重做
- 新增命令只需要新增Command子类,不修改原有代码,符合开闭原则
- 可以组合多个命令成为宏命令,批量执行
❌ 缺点
- 每一个动作都需要创建一个Command类,类数量膨胀
- 命令的逻辑会分散在大量命令类中,增加阅读成本
五、框架源码应用
- JDK
java.lang.Runnable是命令模式思想 - Spring JmsTemplate 消息发送任务
- Quartz 定时任务 Job
- Struts Action
六、小结
命令模式核心:把请求封装成独立命令对象,分离调用者与执行者,支持撤销、任务队列。
判断点:需要把动作抽象成对象,支持排队、日志、撤销,优先命令模式。
0 条笔记