命令模式
1/25/24About 4 min
请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

命令模式的主要角色包括:
- 命令接口 Command: 声明执行操作的接口
- 具体命令 ConcreteCommand: 实现执行操作的具体命令类。包含了对接收者的引用,通过调用接收者的方法来完成请求的处理。
- 请求者 Invoker: 要求命令对象执行请求
- 接受者 Receiver: 知道如何执行与执行请求相关的操作
特点
- 将请求者与接收者分离
- 容易扩展新的命令,不用修改已有类
- 命令对象可以进行功能扩展,如撤销、记录、排队等
代码实现
命令接口
public interface Command {
public void execute();
}具体命令
具体命令类中包含了接收者的引用,通过接收者来处理具体命令。
public class ConcreteCommand implements Command {
private Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
@Override
public void execute() {
receiver.action();
}
}接收者
public class Receiver {
public void action() {
System.out.println("Called Receiver.action()");
}
}调用者
调用者用于发送命令,通过将请求传递给命令对象来实现。
public class Invoker {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void executeCommand() {
command.execute();
}
}测试
public class Client {
public static void main(String[] args) {
Receiver receiver = new Receiver();
Command command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.setCommand(command);
invoker.executeCommand();
}
}命令模式与其他模式的对比
| 模式 | 功能 | 实现方式 | 适用场景 |
|---|---|---|---|
| 命令模式 | 封装请求为对象 | 将请求封装为命令,支持队列、撤销等操作 | 需要支持请求的队列化、日志记录或撤销时 |
| 策略模式 | 封装可替换算法 | 定义算法族,运行时动态切换 | 需要在运行时选择不同算法实现时 |
| 状态模式 | 封装对象状态行为 | 对象状态变化时改变其行为 | 对象行为依赖于其状态,且状态可动态变化时 |
| 观察者模式 | 一对多依赖通知 | 主题维护观察者列表,状态变化时通知所有观察者 | 一个对象状态变化需要影响多个其他对象时 |
总结
核心思想
命令模式的核心思想是将请求封装为命令对象,使请求的发送者和接收者解耦。通过命令对象,可以实现请求的队列化、日志记录、撤销/重做等功能,符合单一职责原则和开放封闭原则。
主要角色
- 命令接口(Command):声明执行操作的接口
- 具体命令(ConcreteCommand):实现命令接口,包含接收者引用,调用接收者方法执行请求
- 请求者(Invoker):发送命令,要求命令对象执行请求
- 接收者(Receiver):执行命令的具体操作,实现业务逻辑
实现方式
- 定义命令接口,包含执行操作的方法
- 具体命令类实现命令接口,持有接收者引用,调用接收者方法
- 请求者类持有命令对象,提供执行命令的方法
- 接收者类实现具体业务逻辑
- 客户端创建接收者、命令和请求者对象,建立它们之间的关联
优缺点
优点:
- 符合单一职责原则,请求发送者与接收者解耦
- 符合开放封闭原则,添加新命令只需添加新的具体命令类
- 支持请求的队列化、日志记录、撤销/重做等功能
- 便于实现命令的组合和宏命令
- 提高了代码的可维护性和扩展性
缺点:
- 可能导致系统中命令类的数量增加
- 命令对象可能会占用较多内存
- 系统复杂度增加,需要理解多个角色之间的交互
- 命令的撤销/重做功能实现较为复杂
适用场景
- 需要将请求发送者与接收者解耦时
- 需要支持请求的队列化、日志记录或撤销/重做操作时
- 需要实现命令的组合和宏命令时
- 需要在运行时动态选择和执行命令时
- 需要将命令作为参数传递或存储时
实际应用
- 图形界面的菜单命令:每个菜单项对应一个命令对象,点击菜单项执行相应命令
- 撤销/重做功能:文本编辑器、绘图软件等支持撤销和重做操作
- 任务调度系统:将任务封装为命令,放入队列中按顺序执行
- 日志系统:记录用户操作命令,支持系统恢复
- 事务处理系统:将事务操作封装为命令,支持事务的提交和回滚