命令模式
命令模式
命令模式是一种行为型设计模式,它将请求封装成对象,以便在不同的请求、日志或事务中参数化其他对象,并支持可撤销操作。
适用场景
- 当需要将请求、操作或行为放入队列中、记录日志、支持撤销等功能时,可使用命令模式;
- 当需要以不同的参数来调用相同方法时,可使用命令模式;
- 当需要执行一组操作,而不在意具体的执行过程时,可使用命令模式。
示例
我们以电视机为例来说明命令模式的实现。
假设我们有一个电视机类,有打开电视、关闭电视、调高音量和调低音量四个方法。现在需要将这四个操作封装成命令对象,支持队列、日志和可撤销操作,我们按照以下步骤来实现命令模式:
定义命令接口
public interface Command {
void execute();
void undo();
}
命令接口定义了两个方法,execute()
方法用于执行命令,undo()
方法用于撤销命令。
实现具体命令类
public class TurnOnCommand implements Command {
private TV tv;
public TurnOnCommand(TV tv) {
this.tv = tv;
}
public void execute() {
tv.turnOn();
}
public void undo() {
tv.turnOff();
}
}
public class TurnOffCommand implements Command {
private TV tv;
public TurnOffCommand(TV tv) {
this.tv = tv;
}
public void execute() {
tv.turnOff();
}
public void undo() {
tv.turnOn();
}
}
public class VolumeUpCommand implements Command {
private TV tv;
public VolumeUpCommand(TV tv) {
this.tv = tv;
}
public void execute() {
tv.volumeUp();
}
public void undo() {
tv.volumeDown();
}
}
public class VolumeDownCommand implements Command {
private TV tv;
public VolumeDownCommand(TV tv) {
this.tv = tv;
}
public void execute() {
tv.volumeDown();
}
public void undo() {
tv.volumeUp();
}
}
定义了四个具体命令类,分别对应四个操作。
实现命令调用者
public class RemoteControl {
private List<Command> commandQueue = new ArrayList<>();
public void press(Command command) {
command.execute();
commandQueue.add(command);
}
public void undo() {
if (commandQueue.size() > 0) {
Command command = commandQueue.get(commandQueue.size() - 1);
command.undo();
commandQueue.remove(command);
}
}
}
命令调用者具有press()
和undo()
两个方法,press()
方法用于执行命令,同时将命令添加到命令队列中;undo()
方法用于撤销命令,从命令队列中取出最后一个命令并执行其undo()
方法。
客户端使用
TV tv = new TV();
RemoteControl control = new RemoteControl();
control.press(new TurnOnCommand(tv));
control.press(new VolumeUpCommand(tv));
control.press(new VolumeUpCommand(tv));
control.press(new VolumeDownCommand(tv));
control.undo();
客户端使用时,创建电视机实例和遥控器实例,然后按照需要执行命令和撤销命令。
总结
使用命令模式,可以将复杂的操作封装成命令,从而实现队列、日志和撤销等功能,同时也符合面向对象的设计原则。但是,命令模式会增加系统的复杂度和代码量,需要权衡利弊后再做决定。