C++之命令(Command)模式

举报
Hermit_Rabbit 发表于 2022/11/29 21:58:42 2022/11/29
【摘要】 0. 简介我们在遇到类似GUI中多种Button点击功能的操作时,我们应该将请求的所有细节 (例如调用的对象、 方法名称和参数列表) 抽取出来组成命令类, 该类中仅包含一个用于触发请求的方法。命令模式就是这样一种行为设计模式, 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 并能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中, 且能实现可撤销操作。 1. 命令模式示意...

0. 简介

我们在遇到类似GUI中多种Button点击功能的操作时,我们应该将请求的所有细节 (例如调用的对象、 方法名称和参数列表) 抽取出来组成命令类, 该类中仅包含一个用于触发请求的方法。

命令模式就是这样一种行为设计模式, 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 并能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中, 且能实现可撤销操作。

1. 命令模式示意图

命令模式可将特定的方法调用转化为独立对象。 这一改变也带来了许多有趣的应用: 你可以将命令作为方法的参数进行传递、 将命令保存在其他对象中, 或者在运行时切换已连接的命令等。

在这里插入图片描述

  1. Command(抽象命令类):抽象出命令对象,可以根据不同的命令类型。写出不同的实现类

  2. Concrete Command(具体命令类):实现了抽象命令对象的具体实现

  3. Invoker(调用者/请求者):请求的发送者,它通过命令对象来执行请求。一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令来之间存在关联。在程序运行时,将调用命令对象的execute() ,间接调用接收者的相关操作。

  4. Receiver(接收者):接收者执行与请求相关的操作,真正执行命令的对象。具体实现对请求的业务处理。未抽象前,实际执行操作内容的对象。

  5. Client(客户端):在客户类中需要创建调用者对象,具体命令类对象,在创建具体命令对象时指定对应的接收者。发送者和接收者之间没有之间关系。都通过命令对象来调用。

2. 示例程序

责任链模式和命令模式用于处理请求发送者和接收者之间的不同连接方式。责任链按照顺序将请求动态传递给一系列的潜在接收者, 直至其中一名接收者对请求进行处理。命令模式则是在发送者和请求者之间建立单向连接
作为命令模式的作用,非常明显,它可以通过某些行为来参数化对象。从而避免了继承导致的调用与接收的紧耦合。命令模式则是分离了这两者,修改时只需要添加接收者并创建新的实例化具体命令类即可实现整套代码的调用
在这里插入图片描述

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>

using namespace std;

// 接受者,作为最底层的调用
class Receiver
{
public:
        void BakeMutton()
        {
                cout<< "烤羊肉"<< endl;
        }

        void BakeChicken()
        {
                cout<< "烤鸡翅"<< endl;
        }
};

// 基类
class Command
{
public:
        Command(Receiver* pstReceiver):m_pstReceiver(pstReceiver)
        {

        }
        virtual void Excute() = 0;

protected:
        Receiver* m_pstReceiver;
};

// 具体类,用于调用接收者
class ConcreteCommandA: public Command
{
public:
        ConcreteCommandA(Receiver* pstReceiver):Command(pstReceiver)
        {

        }
        virtual void Excute()
        {
                cout<< "ConcreteCommandA excuting......"<< endl;
                m_pstReceiver->BakeMutton();
        }

};

// 具体类,用于调用接收者
class ConcreteCommandB: public Command
{
public:
        ConcreteCommandB(Receiver* pstReceiver):Command(pstReceiver)
        {

        }
        virtual void Excute()
        {
                cout<< "ConcreteCommandB excuting......"<< endl;
                m_pstReceiver->BakeChicken();
        }
};

// 调用者,作为最上层,用于管理具体类的操作,从而对接收者增删
class Invoke
{
public:
        void Add(Command* pstCommand)
        {
                m_vecPstCommand.push_back(pstCommand);
        }
        void Remove(Command* pstCommand)
        {
                m_vecPstCommand.erase(find(m_vecPstCommand.begin(), m_vecPstCommand.end(), pstCommand));
        }
        void RemoveAll()
        {
                m_vecPstCommand.clear();
        }
        void Notify()
        {
                for (typeof(m_vecPstCommand.begin()) it = m_vecPstCommand.begin(); it != m_vecPstCommand.end(); ++it)
                {
                        (*it)->Excute();
                }
        }

private:
        vector<Command*> m_vecPstCommand;
};

int main(int argc, char* argv[])
{
        Receiver* pstReceiver = new Receiver();
        Command* pstConcreteCommandA = new ConcreteCommandA(pstReceiver);
        Command* pstConcreteCommandB = new ConcreteCommandB(pstReceiver);
        Invoke* pstInvoke = new Invoke();

        pstInvoke->Add(pstConcreteCommandA);
        pstInvoke->Add(pstConcreteCommandA);
        pstInvoke->Add(pstConcreteCommandB);
        pstInvoke->Notify();
        cout<< "------------------"<< endl<< endl;

        pstInvoke->Remove(pstConcreteCommandA);  //撤销操作
        pstInvoke->Remove(pstConcreteCommandB);
        pstInvoke->Notify();
        cout<< "------------------"<< endl<< endl;

        return 0;
}

/**
ConcreteCommandA excuting......
烤羊肉
ConcreteCommandA excuting......
烤羊肉
ConcreteCommandB excuting......
烤鸡翅
------------------

ConcreteCommandA excuting......
烤羊肉
------------------ 
**/

…详情请参照古月居

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。