设计模式 —— 命令模式

“行为变化”模式

在组件的构建过程中,组件行为的变化经常到导致组件本身剧烈的变化。“行为变化”模式将组件的行为和组件本身进行解耦,从而支持组件行为的变化,实现两者之间的松耦合。
典型模式:命令模式,访问器模式

命令模式

动机

  • 在软件构建过程,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但是某些场合——比如需要对行为进行“记录、撤销、事物”等处理,这种无法抵御变化的紧耦合是不合适的。
  • 在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,可实现二者解耦。

模式定义

将一个请求(行为)封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。  —— 《设计模式》GOF

UML结构

 

代码示例

 1 #include <iostream>
 2 #include <vector>
 3 #include <string>
 4 using namespace std;
 6 
 7 class Command {
 8 public:
 9     virtual void execute() = 0;
10 };
11 
12 class ConcreteCommand1 : public Command {
13     string arg;
14 public:
15     ConcreteCommand1(const string & a) : arg(a) {}
16     void execute() override {
17         cout<< "#1 process..."<<arg<<endl;
18     }
19 };
20 
21 class ConcreteCommand2 : public Command {
22     string arg;
23 public:
24     ConcreteCommand2(const string & a) : arg(a) {}
25     void execute() override {
26         cout<< "#2 process..."<<arg<<endl;
27     }
28 };
29         
30         
31 class MacroCommand : public Command { 
32     vector<Command*> commands;
33 public:
34     void addCommand(Command *c) { commands.push_back(c); }
35     void execute() override {
36         for (auto &c : commands) {
37             c->execute();
38         }
39     }
40 };
41         
42 int main() {
43 
44     ConcreteCommand1 command1(receiver, "Arg ###");
45     ConcreteCommand2 command2(receiver, "Arg $$$");
46     
47     MacroCommand macro;
48     macro.addCommand(&command1);
49     macro.addCommand(&command2);
50     
51     macro.execute();
52 
53 }

Command:声明执行操作的接口;
ConcreteCommand:将一个接收者对象绑定于一个动作,之后,调用接收者相应的操作,以实现Execute来完成相应的命令;
Client:创建一个具体命令对象,但是并没有设定它的接收者;
Invoker:要求该命令执行这个请求;
Receiver:知道如何实施与执行一个请求相关的操作,任何类都可能作为一个接收者。

以上这些对象是按照下面的方式进行协作的:

  1. Client创建一个ConcreteCommand命令对象,并指定它的Receiver对象;
  2. Invoker对象存储该ConcreteCommand对象;
  3. 该Invoker通过调用Command对象的Execute操作来提交一个请求。如果这个命令请求是可以撤销的,ConcreteCommand就执行Execute操作之前存储当前状态以用于取消该命令请求;
  4. ConcreteCommand对象调用Receiver的一些操作以执行该请求。
 
总结:
  • Cammand模式的根本目的在于将“行为请求者”与“行为实现者”解耦,在面向对象语言中,常见的手段“将行为抽象为对象”。
  • 实现Commmad接口的具体命令对象ConcreteCommand有时候根据需要可能会保存一些额外的状态信息。通过使用Composite模式,可以将多个命令封装为一个复合命令。
  • Command模式与C++中函数对象有些类似。但两者定义行为接口规范有所区别:Command以面向对象的“接口-实现”来定义行为接口规范,更严格,但有性能损失;C++函数对象以函数签名来定义接口规范,更灵活,性能更高。
原文地址:https://www.cnblogs.com/y4247464/p/15523305.html