美文网首页
S8.命令模式

S8.命令模式

作者: 拂去尘世尘 | 来源:发表于2022-01-03 20:47 被阅读0次

    命令模式

    命令模式是一种行为模式,用于将请求或频繁调用关系管理起来,封装成对象行为。

    意义

    在平常的设计中,对于不同模块之间调用关系,通常通过头文件直接调用接口即可。随着需求的增多,调用越来越多。最终维护起来会发现如下问题:

    • 代码裁剪时任务量大。由于调用过多,且调用关系散落各处,导致裁剪代码时,不敢轻易下手。
    • 各个组件关系复杂。在实际的编程中,经常会遇到一些“特殊”场景,需要特殊处理(组件之间调用),而这些代码又未规范起来。因此在新人维护代码时,会忽略这些特殊场景。更恐怖的是,遇到重复的需求,又加上重复的代码。
    • 代码变得“不纯粹”。

    命令模式可以解决以上问题。

    类图

    命令模式

    Invoker:

    执行实例,此对象完成命令申请和命令响应的整个流程。

    Command:

    命令对象基类,定义命令类的模板。

    LedCmd、MotorCmd:

    具体的命令类,其内部会持有Receiver的指针,用于将具体的命令实例和响应实例绑定。此类中,可以做一些对命令的管理等操作。

    Receiver:

    命令响应类,用于响应某个命令的执行动作。

    Client:

    客户端代码,如果规范起来的话,Client应只能访问对外释放的接口。在此指定命令与指定响应行为绑定。

    总结

    • 命令模式将模块之间的调用关系,分离为命令发起、命令处理和命令响应,从而完成代码间的解耦。
    • 命令对象与响应对象通过动态的注册的方式来实现,更容易完成响应者的替换。
    • 加入新的需求时,只需要增加新的对象即可,无需修改原先的业务代码,更加安全。
    • 但是此种命令模式,客户端要创建和销毁很多实例,这对于使用者来说是麻烦的操作。优化代码已经完成,等后续总结一篇来介绍。可公众号获取优化的代码。

    源码

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    // 命令响应
    class Receiver
    {
    public:
        explicit Receiver(string operation)
        {
            mOperation = operation;
        }
    
        void Action()
        {
            cout << mOperation << endl;
        }
    
    private:
        string mOperation;
    };
    
    class Command
    {
    public:
        virtual ~Command()
        {
    
        }
    
        virtual void Execute() = 0;
    
    protected:
        Command()
        {
    
        }
    };
    
    class LedCmd : public Command
    {
    public:
        void Execute()
        {
            if (NULL != mRcv) {
                this->mRcv->Action();
            }
        }
    
        explicit LedCmd(Receiver *pRcv)
        {
            if (NULL != pRcv) {
                mRcv = pRcv;
            }
            else
            {
                mRcv = NULL;
                cout << "Error: Param failed!" << endl;
            }
        }
    
    private:
        Receiver *mRcv;
    };
    
    class MotorCmd : public Command
    {
    public:
        void Execute()
        {
            if (NULL != mRcv) {
                this->mRcv->Action();
            }
        }
    
        explicit MotorCmd(Receiver *pRcv)
        {
            if (NULL != pRcv) {
                mRcv = pRcv;
            }
            else
            {
                mRcv = NULL;
                cout << "Error: Param failed!" << endl;
            }
        }
    
    private:
        Receiver *mRcv;
    };
    
    class Invoker
    {
    public:
        explicit Invoker(Command *pCmd)
        {
            if (NULL != pCmd)
            {
                mCmd = pCmd;
            }
            else
            {
                mCmd = NULL;
                cout << "Error: Param failed!" << endl;
            }
        }
    
        // 所有的命令响应动作都会经此接口触发, 可以在此处实现对命令的管理设计
        void Invoke()
        {
            if (NULL != mCmd) {
                mCmd->Execute();
            }
            else {
                cout << "Error: no action" << endl;
            }
        }
    
    private:
        Command *mCmd;
    };
    
    int main(int argc, char *argv[])
    {
        Receiver *theLedRcv = new Receiver("Led");
        LedCmd *theLedCmd = new LedCmd(theLedRcv);
        Invoker *theLedManager = new Invoker(theLedCmd);
        theLedManager->Invoke();
    
        Receiver *theMotorRcv = new Receiver("Motor");
        LedCmd *theMotorCmd = new LedCmd(theMotorRcv);
        Invoker *theMotorManager = new Invoker(theMotorCmd);
        theMotorManager->Invoke();
    
        delete theLedRcv;
        delete theLedCmd;
        delete theLedManager;
    
        delete theMotorRcv;
        delete theMotorCmd;
        delete theMotorManager;
    
        return 0;
    }
    
    $ ./a.out 
    Led
    Motor
    

    相关文章

      网友评论

          本文标题:S8.命令模式

          本文链接:https://www.haomeiwen.com/subject/oyhfcrtx.html