可撤销命令设计模式是一种行为模式,它扩展了命令模式,允许撤销操作。当您想在应用程序中实现“撤销”或“重做”等功能时,此模式非常有用。下面详细介绍了该模式的工作原理及其实现方式。
关键组件
- 命令接口:这定义了命令的契约,通常使用诸如execute()和unexecute()(撤消命令)之类的方法。
- 具体命令:接口的具体实现Command,其中每个命令都封装了一个特定的操作以及如何撤消它。它维护撤消自身所需的状态。
- Invoker:此对象触发命令的执行。它还可以维护已执行命令的历史堆栈,以便在撤消/重做操作时轻松访问。
- 接收者:实际执行工作的对象。命令对象将把工作委托给此接收者。
- 历史堆栈:维护的已执行命令堆栈,以允许应用程序回顾先前执行的命令并撤消它们。
Java 中的示例
这是 Java 中可撤消命令模式的一个示例。
步骤 1:定义命令接口
interface Command { void execute(); void unexecute(); }
|
步骤 2:创建接收器
接收器可以是任何东西,但假设我们有一个TextEditor允许添加或删除文本的接收器。
class TextEditor { private StringBuilder text = new StringBuilder();
public void addText(String newText) { text.append(newText); }
public void removeText(int length) { text.delete(text.length() - length, text.length()); }
public String getText() { return text.toString(); } }
|
步骤 3:实施具体命令
让我们创建两个命令:一个用于添加文本,一个用于删除文本。
class AddTextCommand implements Command { private TextEditor editor; private String text;
public AddTextCommand(TextEditor editor, String text) { this.editor = editor; this.text = text; }
@Override public void execute() { editor.addText(text); }
@Override public void unexecute() { editor.removeText(text.length()); } }
|
步骤 4:实现调用程序
将Invoker跟踪命令历史并管理撤消操作。
import java.util.Stack;
class CommandInvoker { private Stack<Command> commandHistory = new Stack<>();
public void executeCommand(Command command) { command.execute(); commandHistory.push(command); }
public void undo() { if (!commandHistory.isEmpty()) { Command command = commandHistory.pop(); command.unexecute(); } } }
|
步骤5:使用模式
以下是我们使用这个Undoable Command模式的方法。
public class Main { public static void main(String[] args) { TextEditor editor = new TextEditor(); CommandInvoker invoker = new CommandInvoker();
Command addHello = new AddTextCommand(editor, "Hello "); Command addWorld = new AddTextCommand(editor, "World!");
invoker.executeCommand(addHello); invoker.executeCommand(addWorld);
System.out.println("After additions: " + editor.getText());
invoker.undo(); System.out.println("After undo: " + editor.getText());
invoker.undo(); System.out.println("After second undo: " + editor.getText()); } }
|
优点
- 关注点分离:每个命令都被封装为一个对象,从而可以轻松添加、删除或修改命令,而无需更改其他代码。
- 撤消/重做支持:该模式本质上提供了一种实现撤消/重做功能的方法。
- 可扩展性:无需改变现有代码即可添加新命令。
使用案例
- 文本编辑器(撤消/重做操作)
- 绘图应用程序(撤消/重做形状和转换)
- 数据库中的事务管理(回滚)
可撤消命令模式在用户操作需要可逆的应用程序中特别有用,它提供了一种灵活而强大的方式来处理复杂的用户交互序列。