命令模式(Command Pattern)是一种行为设计模式,它将请求封装为一个对象,从而使你可以用不同的请求、队列或者日志来参数化对象。命令模式允许请求的发送者与接收者完全解耦。
关键组成部分
-
Command(命令接口)
定义执行命令的接口,通常包括一个 execute() 方法。 -
ConcreteCommand(具体命令类)
实现 Command 接口,负责调用接收者的相关操作。
它将一个接收者对象绑定到具体的操作上,并通过调用接收者的方法执行请求。 -
Receiver(接收者)
执行具体操作的类。命令执行时,会调用接收者的操作。 -
Invoker(调用者)
持有命令对象,负责调用命令的 execute() 方法。 -
Client(客户端)
创建具体命令对象并设置其接收者,然后将命令传递给调用者。
使用场景
- 请求解耦:当需要将请求的发送者与接收者解耦时。
- 操作记录:需要支持操作的撤销与重做功能。
- 宏命令:需要组合多个操作作为一个整体执行。
示例代码
以下是一个简单的 Java 实现:
// Command 接口
interface Command {
void execute();
}
// Receiver 接收者
class Light {
public void turnOn() {
System.out.println("The light is ON");
}
public void turnOff() {
System.out.println("The light is OFF");
}
}
// ConcreteCommand 实现具体命令
class TurnOnLightCommand implements Command {
private Light light;
public TurnOnLightCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
}
class TurnOffLightCommand implements Command {
private Light light;
public TurnOffLightCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
}
// Invoker 调用者
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
// Client 客户端
public class CommandPatternDemo {
public static void main(String[] args) {
Light light = new Light();
Command turnOn = new TurnOnLightCommand(light);
Command turnOff = new TurnOffLightCommand(light);
RemoteControl remote = new RemoteControl();
// 开灯
remote.setCommand(turnOn);
remote.pressButton();
// 关灯
remote.setCommand(turnOff);
remote.pressButton();
}
}
优缺点
- 优点
解耦:请求发送者和接收者分离。
灵活扩展:可以很容易地增加新的命令类型。
支持撤销和重做:通过记录命令历史实现。 - 缺点
类数量增加:每个命令都需要一个类,可能导致系统复杂度上升。
系统开销:对于简单操作,命令模式显得较为繁琐。
常见应用
事务脚本:数据库操作、日志记录等。
GUI 按钮操作:每个按钮的点击都可以绑定一个命令。
任务队列:任务调度和异步处理。