命令模式(Command Pattern)
1. 概述
命令模式是一种行为型设计模式,它将请求封装成对象,从而使得你可以用不同的请求对客户进行参数化,排队请求或记录日志,并支持可撤销的操作。命令模式的核心思想是将“动作请求者”与“动作执行者”解耦,使得请求者无需了解执行者的任何细节。
2. 适用场景
- 需要将请求封装为对象:以便在不同的时间或条件下执行。
- 需要对请求进行参数化处理:以便在执行时,传递不同的请求内容。
- 需要支持撤销和恢复功能:例如在文本编辑器、事务管理等场景。
- 需要记录日志以支持请求重放:可以记录命令请求以备将来使用。
- 需要将操作的执行排入队列:例如任务调度系统。
3. 结构
- Command(命令接口):定义执行命令的接口,声明一个
execute()
方法。 - ConcreteCommand(具体命令类):实现
Command
接口,将接收者对象绑定到这个命令,调用接收者的相应操作来实现execute()
方法。 - Receiver(接收者):真正执行命令相关操作的对象。
- Invoker(调用者):持有命令对象并通过调用命令的
execute()
方法来执行命令。 - Client(客户端):创建具体命令对象并设置其接收者,通常还会将命令对象传递给调用者。
4. 示例代码
假设我们要实现一个简单的遥控器,它可以控制电灯的开关。我们可以使用命令模式将遥控器的操作与电灯的具体实现解耦。
1. 定义命令接口
interface Command {
void execute();
}
2. 实现具体命令类
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
}
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
}
3. 创建接收者类
class Light {
public void turnOn() {
System.out.println("The light is on.");
}
public void turnOff() {
System.out.println("The light is off.");
}
}
4. 实现调用者类
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
5. 使用命令模式的客户端
public class CommandPatternDemo {
public static void main(String[] args) {
// 创建接收者对象
Light livingRoomLight = new Light();
// 创建命令对象并设置接收者
Command lightOn = new LightOnCommand(livingRoomLight);
Command lightOff = new LightOffCommand(livingRoomLight);
// 创建调用者对象
RemoteControl remote = new RemoteControl();
// 将命令对象传递给调用者并执行命令
remote.setCommand(lightOn);
remote.pressButton(); // 输出:The light is on.
remote.setCommand(lightOff);
remote.pressButton(); // 输出:The light is off.
}
}
6. 运行结果
The light is on.
The light is off.
7. 分析
- 解耦命令的请求者和执行者:命令模式将命令的请求和执行解耦,调用者无需关心命令的具体实现,只需要执行
execute()
方法。 - 灵活扩展命令:可以很容易地添加新命令,不需要修改现有代码,只需要创建新的具体命令类。
- 支持撤销操作:通过在命令类中添加
undo()
方法,可以实现命令的撤销功能。
8. 优缺点
-
优点:
- 解耦请求和执行:请求发送者与请求处理者解耦,便于扩展和维护。
- 命令的可扩展性:可以方便地添加新的命令类。
- 支持撤销和恢复:通过在命令中保存状态信息,可以实现命令的撤销与恢复。
- 支持宏命令:通过将多个命令组合在一起,形成宏命令,从而一次执行一组操作。
-
缺点:
- 增加类的数量:命令模式引入了大量的新类,可能会增加系统的复杂性。
- 命令管理的复杂性:当有很多命令需要管理时,可能会导致命令管理的复杂性增加。
9. 适用场景扩展
- 事务管理系统:将数据库操作封装成命令对象,支持事务的撤销和恢复。
- 图形用户界面(GUI):将用户操作封装成命令对象,以支持撤销和重做功能。
- 任务调度系统:将任务封装成命令对象,可以排队执行、延迟执行或重复执行。
命令模式通过将请求封装为对象,实现了请求者与执行者的解耦,便于扩展和管理请求操作。它适用于需要对请求进行封装、参数化处理、撤销恢复等功能的场景。