命令模式(Command Pattern)
命令模式(Command Pattern)是一种行为设计模式,它将请求封装成一个对象,从而允许你使用不同的请求、队列或日志来参数化其他对象,同时支持请求的撤销与恢复。以下从多个方面详细介绍命令模式。
模式结构与角色
命令模式包含以下主要角色:
- 命令接口(Command):定义了执行操作的抽象方法,通常是
execute()
方法,具体命令类需要实现该接口。 - 具体命令类(Concrete Command):实现了命令接口,持有一个接收者对象的引用,并在
execute()
方法中调用接收者的相应操作。 - 接收者(Receiver):执行具体的业务逻辑,是命令真正的执行者。
- 调用者(Invoker):负责调用命令对象的
execute()
方法,它不关心具体的命令内容,只负责触发命令执行。 - 客户端(Client):创建具体命令对象,并将其关联到接收者和调用者。
代码示例
以下是一个简单的命令模式示例,模拟一个简单的家电控制系统,包含电灯的打开和关闭操作:
// 命令接口
interface Command {
void execute();
void undo();
}
// 接收者:电灯
class Light {
public void turnOn() {
System.out.println("Light is on");
}
public void turnOff() {
System.out.println("Light is off");
}
}
// 具体命令类:打开电灯命令
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
@Override
public void undo() {
light.turnOff();
}
}
// 具体命令类:关闭电灯命令
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
@Override
public void undo() {
light.turnOn();
}
}
// 调用者:遥控器
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndoButton() {
command.undo();
}
}
// 客户端代码
public class CommandPatternExample {
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.pressUndoButton();
// 设置另一个命令并执行
remoteControl.setCommand(lightOffCommand);
remoteControl.pressButton();
// 撤销操作
remoteControl.pressUndoButton();
}
}
代码解释
- 命令接口
Command
:定义了execute()
和undo()
方法,分别用于执行命令和撤销命令。 - 接收者
Light
:包含turnOn()
和turnOff()
方法,用于控制电灯的开关。 - 具体命令类
LightOnCommand
和LightOffCommand
:实现了Command
接口,分别负责打开和关闭电灯,并提供了相应的撤销操作。 - 调用者
RemoteControl
:通过setCommand()
方法设置要执行的命令,通过pressButton()
方法执行命令,通过pressUndoButton()
方法撤销命令。 - 客户端代码:创建了接收者、具体命令和调用者,并进行命令的设置和执行。
优点
- 解耦请求和执行:命令模式将请求的发送者和接收者解耦,使得发送者不需要知道接收者的具体信息,只需要发送命令即可。
- 可扩展性:可以很容易地添加新的命令类,而不需要修改现有的调用者和接收者代码。
- 支持撤销和恢复:通过实现
undo()
方法,可以方便地实现命令的撤销和恢复功能。 - 支持队列和日志:可以将命令对象存储在队列中,实现命令的排队执行;也可以将命令记录到日志中,实现命令的回放和审计。
缺点
- 类的数量增加:随着命令的增加,会产生大量的具体命令类,导致系统的类数量增多,增加了系统的复杂度。
- 代码复杂度:对于简单的操作,使用命令模式可能会增加代码的复杂度,不太适合简单的场景。
应用场景
- 撤销和恢复功能:如文本编辑器的撤销和重做操作、游戏中的回退功能等。
- 队列和日志系统:如任务调度系统、事务处理系统等,将命令对象存储在队列中,按顺序执行。
- 菜单系统:如图形界面的菜单命令,每个菜单项对应一个命令对象,点击菜单项时执行相应的命令。
Java设计模式 文章被收录于专栏
设计模式是软件开发中针对反复出现的问题所总结归纳出的通用解决方案,它可以帮助开发者更高效地构建软件系统,提升代码的可维护性、可扩展性和可复用性。