命令模式(Command Pattern)
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为一个对象,从而让你可用不同的请求对客户端进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。命令模式将调用操作的对象和知道如何实现该操作的对象解耦。
命令模式包含以下几个角色:
- Command:命令接口,定义执行命令的方法 execute。
- ConcreteCommand:具体的命令类,实现 Command 接口,封装了命令的执行者和参数。
- Invoker:调用者,负责调用命令对象执行命令。
- Receiver:接收者,知道如何实现命令所要求的操作,任何类都可以成为一个接收者。
- Client:客户端,创建具体的命令对象并设置其接收者。
下面是一个简单的例子来说明命令模式:
// Receiver
class Light {
public void on() {
System.out.println("灯已打开!");
}
public void off() {
System.out.println("灯已关闭!");
}
}
// Command
interface Command {
void execute();
}
// ConcreteCommand
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
// Invoker
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
// Client
public class Client {
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);
remoteControl.pressButton();
remoteControl.setCommand(lightOffCommand);
remoteControl.pressButton();
}
}
在这个示例中,我们使用命令模式来控制灯的开关。Light 类是接收者,负责执行灯的打开和关闭操作。Command 接口定义了命令的执行方法 execute。LightOnCommand 和 LightOffCommand 类是具体的命令类,它们实现了 Command 接口,将灯的打开和关闭操作封装在命令对象中。RemoteControl 类是调用者,负责调用命令对象执行命令。Client 类创建具体的命令对象并设置其接收者。
在客户端代码中,我们首先创建一个 Light 对象,然后创建 LightOnCommand 和 LightOffCommand 对象,并分别将它们设置为 RemoteControl
的命令对象。最后,我们调用 RemoteControl 对象的 pressButton 方法来执行命令。
命令模式的优点在于它能够让请求的发送者和接收者解耦,请求发送者只需要知道如何发送请求,而不需要知道请求是如何被接收和处理的。此外,命令模式还可以将多个命令对象组合成一个复合命令,以实现批处理等功能。另外,命令模式还可以支持撤销操作,只需在命令对象中添加一个 undo 方法即可。
命令模式的缺点在于它可能会导致类的数量增加,特别是在有多个接收者的情况下。此外,命令模式还可能导致代码复杂化,因为需要定义多个类来封装不同的命令操作。
下面是命令模式的 UML 类图:
+------------------+ +------------------------+ +----------------+
| Command | | Receiver | | Invoker |
+------------------+ +------------------------+ +----------------+
| + execute() | | + action() | | + setCommand() |
+------------------+ +------------------------+ | + pressButton()|
△ △ +----------------+
| | △
+------------------+ +---------------------+ |
| ConcreteCommand1 | | ConcreteCommand2 | |
+------------------+ +---------------------+ |
| + execute() | | + execute() | |
+------------------+ +---------------------+ |
△ △ |
| | |
+------------------+ +----------------------+ |
| Client | | Receiver2 | |
+------------------+ +----------------------+ |
| | | + action() | |
| | +----------------------+ |
| | |
| | |
| + main() | |
+------------------+
在上述 UML 类图中,Command 是命令的接口,它定义了命令对象需要实现的方法 execute()。ConcreteCommand1 和 ConcreteCommand2 是具体的命令类,它们实现了 Command 接口,并封装了命令的接收者对象。Invoker 是调用者,它负责调用命令对象的 execute() 方法。Receiver 是接收者,它定义了命令所需的操作。Client 是客户端,它创建具体的命令对象并设置其接收者。