1. 模式动机
在软件设计中, 我们经常需要向某些对象发送请求, 但是并不知道请求的接收者是谁, 也不知道被请求的操作是哪个, 我们只需在程序运行时指定具体的请求接收者即可, 此时, 可以使用命令模式来进行设计, 使得请求发送者与请求接收者消除彼此之间的耦合, 让对象之间的调用关系更加灵活.
命令模式可以对发送者和接收者完全解耦, 发送者与接收者之间没有直接引用关系, 发送请求的对象只需要知道如何发送请求, 而不必知道如何完成请求. 这就是命令模式的模式动机.
2. 模式定义
命令模式(Command Pattern): 将一个请求封装为一个对象, 从而使我们可用不同的请求对客户进行参数化; 对请求排队或者记录请求日志, 以及支持可撤销的操作.
命令模式是一种对象行为型模式, 其别名为动作 (Action) 模式或事务 (Transaction) 模式.
3. 模式结构
抽象命令类(Command): 声明执行命令的接口, 拥有执行命令的抽象方法 execute().
具体命令角色(Concrete Command): 是抽象命令类的具体实现类, 它拥有接收者对象, 并通过调用接收者的功能来完成命令要执行的操作.
实现者 / 接收者(Receiver): 执行命令功能的相关操作, 是具体命令对象业务的真正实现者.
调用者 / 请求者(Invoker): 是请求的发送者, 它通常拥有很多的命令对象, 并通过访问命令对象来执行相关请求, 它不直接访问接收者.
具体调用顺序为 Client => Invoker => Concreate Command => Receiver.
Invoker 并不直接调用 Receiver, 而是通过具体命令对象来调用实现者.
4. 模式代码
- # 实现者 / 接受者
- public class Receiver {
- public void action() {
- System.out.println("接受者的 Action 方法");
- }
- }
- # 抽象命令类
- public abstract class Command {
- public abstract void execute();
- }
- # 具体命令类, 内部 new 了一个实现者的对象
- public class ConcreteCommand extends Command {
- private Receiver receiver;
- public ConcreteCommand() {
- this.receiver = new Receiver();
- }
- @Override
- public void execute() {
- receiver.action();
- }
- }
- # 调用者 / 请求者, 通过赋予不同的 command 值来调用不同的的 command
- public class Invoker {
- private Command command;
- public Invoker(Command command) {
- this.command = command;
- }
- public void setCommand(Command command) {
- this.command = command;
- }
- public void call() {
- System.out.println("call 执行命令 Command");
- command.execute();
- }
- }
- # Client
- public class Client {
- public static void main(String[] args) {
- Command cmd = new ConcreteCommand();
- Invoker invoker = new Invoker(cmd);
- invoker.call();
- }
- }
首先把它们的调用关系理清楚了就明白这个模式了.
5. 总结
分析
命令模式的本质是对命令进行封装, 将发出命令的责任和执行命令的责任分割开.
每一个命令都是一个操作: 请求的一方发出请求, 要求执行一个操作; 接收的一方收到请求, 并执行操作.
命令模式允许请求的一方和接收的一方独立开来, 使得请求的一方不必知道接收请求的一方的接口, 更不必知道请求是怎么被接收, 以及操作是否被执行, 何时被执行, 以及是怎么被执行的.
命令模式使请求本身成为一个对象, 这个对象和其他对象一样可以被存储和传递.
命令模式的关键在于引入了抽象命令接口, 且发送者针对抽象命令接口编程, 只有实现了抽象命令接口的具体命令才能与接收者相关联.
优点
降低系统的耦合度.
新的命令可以很容易地加入到系统中.
可以比较容易地设计一个命令队列和宏命令(组合命令).
可以方便地实现对请求的 Undo 和 Redo.
缺点
使用命令模式可能会导致某些系统有过多的具体命令类. 因为针对每一个命令都需要设计一个具体命令类, 因此某些系统可能需要大量具体命令类, 这将影响命令模式的使用.
来源: https://www.cnblogs.com/wuqinglong/p/12484777.html