命令模式(Command Pattern)是一种行为设计模式,它将请求封装成对象,以便参数化对象、延迟执行、记录请求日志、支持可撤销操作等。此模式基于"行动请求者"与"行动执行者"之间解耦的设计思想,使得请求的发送者和接收者之间没有直接的联系,通过命令对象作为中介,这样两者可以独立变化,提高系统的灵活性和可扩展性。
主要参与者:
- Command(命令接口):定义所有命令的公共接口,声明执行操作的抽象方法 execute()。
- ConcreteCommand(具体命令类):实现 Command 接口,对接收到的请求进行封装处理,通常会持有 Receiver 的引用,并调用其方法来完成实际操作。
- Receiver(接收者):真正执行命令中操作的类,包含业务逻辑。它并不知道命令的存在,只是单纯地执行操作。
- Invoker(调用者/请求者):负责调用命令对象的 execute() 方法,发出请求。它并不直接调用接收者的操作方法,而是通过命令对象间接调用。
优点:
- 低耦合:命令模式将调用操作的对象与知道如何实现该操作的对象分离开来,降低了系统的耦合度。
- 扩展性:添加新的命令非常容易,只需要添加新的 ConcreteCommand 类即可,符合"开闭原则"。
- 灵活性:命令可以存储、队列化、记录日志、支持撤销/重做等功能,丰富了系统的可操控性。
- 支持宏命令:可以将多个命令组合成一个复合命令,即一个命令执行多个操作。
应用场景:
- 用户界面(UI)设计,如按钮点击事件的处理。
- 日志记录、事务管理等需要支持回滚操作的场景。
- 支持批处理作业的系统,如定时任务调度。
- 需要提供可撤销/重做功能的软件,如文本编辑器。
示例代码(Java):
下面是一个使用Java实现命令模式的完整示例。在这个例子中,我们将模拟一个智能家居场景,其中包括一个智能灯泡和一个遥控器。遥控器可以用来开关灯泡,而开关操作将通过命令模式来实现。
1. 定义命令接口
首先,定义一个命令接口 Command
,声明执行操作的方法 execute()
。
java
interface Command {
void execute();
}
2. 实现具体命令
接着,创建两个具体命令类 LightOnCommand
和 LightOffCommand
,它们实现了 Command
接口,并且分别对应着打开和关闭灯的操作。每个命令类都会持有一个 Light
对象的引用,以便操作灯。
java
class LightOnCommand implements Command {
private final Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
}
class LightOffCommand implements Command {
private final Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
}
3. 定义接收者
Light
类作为接收者,它包含实际执行动作的方法 turnOn()
和 turnOff()
。
java
class Light {
public void turnOn() {
System.out.println("Light is on");
}
public void turnOff() {
System.out.println("Light is off");
}
}
4. 创建调用者/请求者
RemoteControl
类作为调用者,它持有一个 Command
类型的成员变量,并提供方法 setCommand()
来设置命令,以及 buttonPressed()
来执行当前设置的命令。
java
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void buttonPressed() {
command.execute();
}
}
5. 客户端代码
最后,客户端代码创建 Light
对象、LightOnCommand
和 LightOffCommand
对象,以及 RemoteControl
对象,并通过遥控器控制灯的开关。
java
public class CommandPatternDemo {
public static void main(String[] args) {
// 创建接收者对象
Light light = new Light();
// 创建命令对象
Command lightOnCommand = new LightOnCommand(light);
Command lightOffCommand = new LightOffCommand(light);
// 创建调用者对象
RemoteControl remoteControl = new RemoteControl();
// 设置命令
remoteControl.setCommand(lightOnCommand);
System.out.println("Pressing ON button...");
remoteControl.buttonPressed(); // 输出 "Light is on"
remoteControl.setCommand(lightOffCommand);
System.out.println("Pressing OFF button...");
remoteControl.buttonPressed(); // 输出 "Light is off"
}
}
这个例子展示了如何使用命令模式来解耦请求的发起者(遥控器)和请求的处理者(灯),使得添加新的命令或者更改现有命令的执行逻辑变得简单且灵活。