一、定义
命令模式(Command Pattern)是一种行为型设计模式,其核心思想是将请求(操作)封装为一个独立的对象,使得可以用不同的请求参数化其他对象、队列化请求、记录请求日志,以及支持可撤销的操作。
核心解决的问题
在软件设计中,经常需要将 “发出命令的对象” 和 “执行命令的对象” 解耦。例如:
- 遥控器(发出命令)不需要知道电视(执行命令)的具体工作原理,只需按下按钮即可;
- 文本编辑器的 “撤销” 功能,需要记录历史操作并反向执行。
命令模式通过将 “命令” 封装为对象,让这两者彻底分离,同时支持更灵活的扩展。
二、命令模式的核心角色
命令模式包含 5 个关键角色,它们协同工作完成命令的封装与执行:
- 命令接口(Command)
声明一个执行操作的抽象方法(通常是 Execute()),所有具体命令都需实现该接口。 - 具体命令(ConcreteCommand)
实现命令接口,内部持有一个 “接收者” 对象,并重写Execute()
方法 ——调用接收者的具体操作来完成命令。 - 接收者(Receiver)
实际执行命令的对象,包含具体的业务逻辑(例如 “开灯”“关闭文件” 等操作)。 - 调用者(Invoker)
持有命令对象,负责触发命令的执行(例如按钮、遥控器等)。它不关心命令的具体实现,只需调用命令的Execute()
方法。 - 客户端(Client)
创建具体命令对象,并将其与接收者关联,然后将命令对象交给调用者。
三、工作流程(以 “遥控器控制灯” 为例)
- 客户端创建 “开灯命令”(ConcreteCommand),并将其与 “灯”(Receiver)绑定;
- 调用者(遥控器的按钮)持有这个 “开灯命令”;
- 当用户按下按钮(调用者触发命令),按钮调用命令的 Execute() 方法;
- “开灯命令” 的 Execute() 方法调用 “灯” 的 TurnOn() 方法(接收者实际执行操作)。
四、代码示例
// 1. 命令接口
public interface Command {
void execute();
}
// 2. 接收者(灯)
public class Light {
public void turnOn() {
System.out.println("灯打开了");
}
public void turnOff() {
System.out.println("灯关闭了");
}
}
// 3. 具体命令(关灯命令)
public class TurnOffLightCommand implements Command {
private Light light; // 持有接收者引用
// 构造方法绑定接收者
public TurnOffLightCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff(); // 调用接收者的具体操作
}
}
// 3. 具体命令(开灯命令)
public class TurnOnLightCommand implements Command {
private Light light; // 持有接收者引用
// 构造方法绑定接收者
public TurnOnLightCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn(); // 调用接收者的具体操作
}
}
// 4. 调用者(遥控器)
public class RemoteControl {
private Command command; // 持有命令对象
// 设置命令
public void setCommand(Command command) {
this.command = command;
}
// 触发命令执行(按下按钮)
public void pressButton() {
command.execute();
}
}
// 5. 客户端(测试类)
public class Client {
public static void main(String[] args) {
// 创建接收者对象
Light light = new Light();
// 创建具体命令对象,并绑定接收者
Command turnOnCommand = new TurnOnLightCommand(light);
Command turnOffCommand = new TurnOffLightCommand(light);
// 创建调用者(遥控器)
RemoteControl remote = new RemoteControl();
// 测试开灯命令
remote.setCommand(turnOnCommand);
remote.pressButton(); // 输出:灯打开了
// 测试关灯命令
remote.setCommand(turnOffCommand);
remote.pressButton(); // 输出:灯关闭了
}
}
五、命令模式的优点
- 解耦:发出命令的调用者与执行命令的接收者完全分离,互不依赖。
- 扩展性强:新增命令只需添加新的 ConcreteCommand 类,无需修改现有代码(符合开闭原则)。
- 支持复杂操作:可实现命令队列(批量执行)、日志记录(记录所有操作)、撤销 / 重做(通过反向命令)等功能。
本人水平有限,有错的地方还请批评指正。
典型应用场景
- GUI 按钮操作(每个按钮对应一个命令);
- 文本编辑器的撤销(Undo)/ 重做(Redo)功能;
- 事务处理(批量执行命令,失败时回滚);
- 任务调度(队列化命令,按顺序执行)。
什么是精神内耗?
简单地说,就是心理戏太多,自己消耗自己。
所谓:
言未出,结局已演千百遍;
身未动,心中已过万重山;
行未果,假想灾难愁不展;
事已闭,过往仍在脑中演。