命令模式 (Command Pattern)
命令模式是一种行为设计模式,它将请求封装成对象,从而使您可以用不同的请求、队列或日志来参数化其他对象。命令模式也支持可撤销的操作。
应用场景
- 事务处理系统:需要对一系列操作进行封装,并提供回滚功能。
- GUI开发:例如按钮点击的处理逻辑,可以使用命令模式将操作和按钮的点击事件解耦。
- 宏命令:组合多个操作命令,形成一个复合命令。
- 日志记录:在系统崩溃后,通过日志重现命令执行的过程。
实现方式
1. 基本命令模式
思想:将请求封装成独立的命令对象,使得命令的调用者与执行者解耦。
实现方式:
java
// 命令接口
interface Command {
void execute();
}
// 具体命令
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.on();
}
}
// 接收者
class Light {
public void on() {
System.out.println("The light is on");
}
public void off() {
System.out.println("The light is off");
}
}
// 调用者
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
// 客户端代码
public class CommandPatternDemo {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();
}
}
优点:
- 解耦请求的发送者和接收者:使得发送者不需要知道接收者的具体实现。
- 扩展性强:可以方便地新增命令。
- 支持撤销操作:可以通过存储历史命令来支持撤销和重做操作。
缺点:
- 类的数量增加:每一个具体命令都需要一个对应的类。
2. 带撤销功能的命令模式
思想:在基本命令模式的基础上,增加对撤销操作的支持。
实现方式:
java
// 命令接口
interface Command {
void execute();
void undo();
}
// 具体命令
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.on();
}
public void undo() {
light.off();
}
}
// 具体命令
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
light.off();
}
public void undo() {
light.on();
}
}
// 接收者
class Light {
public void on() {
System.out.println("The light is on");
}
public void off() {
System.out.println("The light is off");
}
}
// 调用者
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}
// 客户端代码
public class CommandPatternDemo {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();
remote.pressUndo();
remote.setCommand(lightOff);
remote.pressButton();
remote.pressUndo();
}
}
优点:
- 支持撤销和重做操作:可以通过存储命令的历史记录来支持撤销和重做。
- 解耦请求的发送者和接收者:发送者不需要知道接收者的具体实现。
缺点:
- 类的数量增加:每一个具体命令都需要一个对应的类。
- 维护命令历史:需要额外的代码来维护命令历史。
3. 宏命令模式
思想:将多个命令组合成一个复合命令,使得一组命令可以一次执行。
实现方式:
java
// 命令接口
interface Command {
void execute();
}
// 具体命令
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.on();
}
}
// 具体命令
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
public void execute() {
light.off();
}
}
// 宏命令
class MacroCommand implements Command {
private List<Command> commands;
public MacroCommand() {
commands = new ArrayList<>();
}
public void addCommand(Command command) {
commands.add(command);
}
public void execute() {
for (Command command : commands) {
command.execute();
}
}
}
// 接收者
class Light {
public void on() {
System.out.println("The light is on");
}
public void off() {
System.out.println("The light is off");
}
}
// 客户端代码
public class MacroCommandPatternDemo {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);
MacroCommand macro = new MacroCommand();
macro.addCommand(lightOn);
macro.addCommand(lightOff);
macro.execute();
}
}
优点:
- 组合命令:可以将多个命令组合成一个复合命令,简化客户端代码。
- 增强灵活性:可以动态添加或删除命令。
缺点:
- 类的数量增加:每一个具体命令都需要一个对应的类。
- 命令依赖:命令之间可能存在依赖关系,需小心处理。
总结
命令模式 | 优点 | 缺点 |
---|---|---|
基本命令模式 | 解耦请求的发送者和接收者,扩展性强 | 类的数量增加 |
带撤销功能的命令模式 | 支持撤销和重做操作,解耦请求的发送者和接收者 | 类的数量增加,维护命令历史 |
宏命令模式 | 组合命令,增强灵活性 | 类的数量增加,命令依赖 |
选择哪种实现方式应根据具体的需求和系统的复杂度来决定。基本命令模式适用于一般的请求封装场景,带撤销功能的命令模式适用于需要撤销和重做操作的场景,宏命令模式适用于需要组合多个操作的场景。通过合理的设计,可以充分利用命令模式的优势,解耦请求的发送者和接收者,提高系统的灵活性和可扩展性。