命令模式(Command Pattern)是一种行为设计模式,它将一个请求或者操作封装为一个对象。这样,你可以用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
1. 概念
命令模式的核心思想是将操作的发起者(调用者)和操作的接收者(执行者)解耦。通过定义一个命令接口,将操作封装在命令对象中,调用者通过命令对象来请求接收者执行操作,而不需要知道具体的操作细节。
2. 组件
• Command(命令接口):定义执行操作的接口。声明执行操作的方法,通常是一个execute方法。
• ConcreteCommand(具体命令):实现Command接口,将一个接收者对象与一个操作绑定。调用接收者对象的操作来执行具体的操作。
• Client(客户端):创建一个ConcreteCommand对象并设置其接收者。
• Invoker(调用者):要求该命令执行这个请求。知道如何调用Command对象执行请求,但不负责创建ConcreteCommand对象,也不负责确定其接收者。
• Receiver(接收者):知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。
3. 代码示例
假设我们有一个简单的文本编辑器,需要实现一个“撤销”功能。
3.1 命令接口
public interface Command {
void execute();
void undo();
}
3.2 具体命令
public class PasteCommand implements Command {
private TextEditor editor;
private String text;
public PasteCommand(TextEditor editor) {
this.editor = editor;
}
@Override
public void execute() {
text = editor.getText();
editor.paste();
}
@Override
public void undo() {
editor.setText(text);
}
}
public class CutCommand implements Command {
private TextEditor editor;
private String text;
public CutCommand(TextEditor editor) {
this.editor = editor;
}
@Override
public void execute() {
text = editor.getText();
editor.cut();
}
@Override
public void undo() {
editor.setText(text);
}
}
3.3 接收者
public class TextEditor {
private String text;
public void setText(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void paste() {
System.out.println("Pasting text: " + text);
}
public void cut() {
System.out.println("Cutting text: " + text);
}
}
3.4 客户端
public class Client {
public static void main(String[] args) {
TextEditor editor = new TextEditor();
editor.setText("Hello, World!");
Command cutCommand = new CutCommand(editor);
Command pasteCommand = new PasteCommand(editor);
cutCommand.execute();
pasteCommand.execute();
cutCommand.undo();
pasteCommand.undo();
}
}
4. 优点
• 解耦调用者和接收者:调用者和接收者之间没有直接的依赖关系,这使得系统更加灵活,易于扩展和维护。
• 支持撤销操作:通过命令对象的undo方法,可以轻松实现撤销操作。
• 支持队列和日志:可以将命令对象存储在队列中,实现命令的延迟执行或按顺序执行。也可以将命令对象记录到日志中,方便后续的调试和分析。
5. 缺点
• 增加系统复杂性:需要引入多个新的对象和接口,增加了系统的复杂性。
• 性能开销:每个命令对象都需要存储状态信息,可能会增加内存消耗和性能开销。
6. 适用场景
• 需要支持撤销操作:当系统需要支持撤销操作时,命令模式是一个很好的选择。
• 需要将请求参数化:当需要将请求参数化并传递给不同的接收者时,命令模式可以很好地实现。
• 需要支持队列和日志:当需要将请求存储在队列中或记录到日志中时,命令模式可以方便地实现这些功能。
命令模式在实际应用中非常广泛,例如在图形用户界面(GUI)编程中,按钮点击事件的处理通常使用命令模式来实现。