• C++设计模式——命令模式 Command


    命令模式,是将一个请求封装为一个对象,从而使我们可以用不同的请求对客户进行参数化、对请求排队或记录请求日志,以及支持可撤销的操作。

    动机(Motivation)

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

    模式定义

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

    要点总结

    • Command模式的根本目的在于将”行为请求者“与”行为实现者“解耦,在面向对象语言中,常见的实现手段是”将行为抽象为对象“。
    • 与C++中的函数对象类似,C++函数对象以函数签名来定义行为接口规范,更灵活性能更高。

    结构(Structure)

    基本代码

    #include <iostream>
    #include <list>
    using namespace std;
    
    // Receiver类,知道如何实施与执行一个与请求相关的操作:
    class Receiver {
    public:
        void Action() {
            cout << "Receiver" << endl;
        }
    };
    
    // Command类,用来声明执行操作的接口
    class Command {
    public:
        virtual void Excute() = 0;
        virtual void setReceiver(Receiver* r) = 0;
        virtual ~Command(){};
    };
    
    // ConcreteCommand类,绑定一个Receiver,调用其相应操作以实现Excute:
    class ConcreteCommand : public Command {
    private:
        Receiver* receiver;
    public:
        void setReceiver(Receiver* r) {
            receiver = r;
        }
        void Excute() {
            //cout << "ConcreteCommand" << endl;
            receiver->Action();
        }
    };
    
    // 要求该命令执行这个请求:
    class Invoker {
    private:
        list<Command* > commands;
    public:
        void setCommand(Command* c) {
            commands.push_back(c);
        }
        void Notify() {
            for (auto c = commands.begin(); c != commands.end(); c++) {
                (*c)->Excute();
            }
        }
    };
    
    // 客户端实现代码:
    int main() {
        Command* c = new ConcreteCommand();
        Receiver* r = new Receiver();
        c->setReceiver(r);
    
        Invoker I;
        i.setCommand(c);
        i.Notify();   // Receiver
    
        delete r;
        delete c;
    
        return 0;
    }

    应用场景

    优点:

    • 能较容易地设计一个命令队列;
    • 在需要的情况下,可以较容易地将命令记入日志;
    • 允许接收请求的一方决定是否要否决请求;
    • 可以轻易地实现对请求的撤销和重做;
    • 增加新的具体命令类很方便;
    • 命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分割开了。
  • 相关阅读:
    【2020】iOS证书(.p12)和描述文件(.mobileprovision)一键申请流程
    苹果开发者账号正在调查原因解答
    【2020最新】苹果iOS开发者到期续费流程
    【2020】联系苹果客服电话入口及步骤
    苹果电脑Transporter App及Windows上传ipa工具Appuploader
    一文学会苹果TestFlight上架详细流程
    iOS APP打包上线App Store七个步骤详解(2020版)
    技术分享 | mysql 表数据校验
    MySQL 自带的4个系统数据库的说明
    linux定时任务crontab怎样执行root命令
  • 原文地址:https://www.cnblogs.com/wkfvawl/p/12799169.html
Copyright © 2020-2023  润新知