• 观察者模式-委托(大话设计模式)C/C++版本


    观察者模式-委托

    先看该常规的没有委托概念的代码,如下:

    非委托

    #include 
    #include 
    #include 
    using namespace std;
    
    class Subject; // 前向声明
    
    // 抽象观察者
    class Observer
    {
    protected:
        string name;
        Subject *sub;
    
    public:
        Observer(string name, Subject *sub)
        {
            this->name = name;
            this->sub = sub;
        }
        virtual void update() = 0;
    };
    
    // 抽象通知者
    class Subject
    {
    protected:
        list<Observer *> observers;
    
    public:
        string event;
        virtual void attach(Observer *) = 0;
        virtual void detach(Observer *) = 0;
        virtual void notify() = 0;
    };
    
    // 具体通知者,秘书
    class Secretary : public Subject
    {
        void attach(Observer *observer) override
        {
            observers.push_back(observer);
        }
    
        void detach(Observer *observer) override
        {
            list<Observer *>::iterator iter = observers.begin();
            while (iter != observers.end())
            {
                if ((*iter) == observer)
                {
                    observers.erase(iter);
                }
                ++iter;
            }
        }
    
        void notify() override
        {
            list<Observer *>::iterator iter = observers.begin();
            while (iter != observers.end())
            {
                (*iter)->update();
                ++iter;
            }
        }
    };
    
    // 具体的观察者,看股票的
    class StockObserver : public Observer
    {
    public:
        StockObserver(string name, Subject *sub) : Observer(name, sub)
        {
        }
        void update() override
        {
            cout << name << " 收到消息:" << sub->event << endl;
            if (sub->event == "梁所长来了!")
            {
                cout << "我马上关闭股票,装做很认真工作的样子!" << endl;
            }
        }
    };
    
    // 具体的观察者,看NBA的
    class NBAObserver : public Observer
    {
    public:
        NBAObserver(string name, Subject *sub) : Observer(name, sub)
        {
        }
        void update() override
        {
            cout << name << " 收到消息:" << sub->event << endl;
            if (sub->event == "梁所长来了!")
            {
                cout << "我马上关闭NBA,装做很认真工作的样子!" << endl;
            }
        }
    };
    
    int main()
    {
        // 创建通知者
        Subject *dwq = new Secretary();
    
        // 被观察的对象
        Observer *xs = new NBAObserver("xiaoshuai", dwq);
        Observer *lm = new StockObserver("limin", dwq);
    
        // 加入观察队列
        dwq->attach(xs);
        dwq->attach(lm);
    
        // 事件
        dwq->event = "去吃饭了!";
        // 通知
        dwq->notify();
        cout << endl;
    
        // 事件
        dwq->event = "梁所长来了!";
        // 通知
        dwq->notify();
        cout << endl;
    
        return 0;
    }
    

    观察者为什么要和委托有联系?

    1. 抽象通知类还是依赖抽象观察者类
    2. 不同的被观察者可能并不相关,所以设计的接口不一定全都是一样的接口名称update.
      总结这两点,就是去除抽象观察者这个基类后,并且该更新状态的接口不同名的情况下,观察者模式仍旧可以成立。

    何谓委托(大概了解即可)

    委托是一种设计原则,指的是一个对象(委托者)将自身的一部分职责或功能交由另一个对象(被委托者)来执行。这种机制允许对象专注于自己的核心功能,同时利用外部对象的专业能力来完成辅助任务。委托强调的是行为的传递和执行,而不是对象所有权或生命周期的管理
    在这里插入图片描述

    那么,C++如何实现委托?

    function+bind
    参考:https://blog.csdn.net/qq_38410730/article/details/103637778
    https://www.cnblogs.com/linuxAndMcu/p/14576162.html#_label1

    # include 
    std::function<函数类型>
    

    std::function是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。

    # include 
    std::bind(函数指针, 绑定对象);
    

    std::bind可以看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来适应原对象的参数列表

    这样就可以实现:直接将具体观察者实例和观察者类状态更新接口函数(即之前的update)绑定。通知类管理的通知对象就从观察者实例变成了观察者的函数对象了。

    也就是达到了:通知类不再依赖抽象观察者类的update接口,而是直接依赖这个绑定的函数对象。这样就可以达到:不需要抽象观察者类并且可以使用不同的接口名。

    委托

    参考:https://blog.csdn.net/weixin_43272766/article/details/94166777

    1. 去除了抽象观察者类
    2. 使用了C++的function+bind实现委托
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    // 
    typedef function<void()> Action;
    
    // 抽象观察者 无
    
    // 抽象通知者
    class Subject
    {
    protected:
        list<Action *> actions;
    
    public:
        string event;
        virtual void attach(Action *a) = 0;
        virtual void detach(Action *a) = 0;
        virtual void notify() = 0;
    };
    
    // 具体通知者,秘书
    class Secretary : public Subject
    {
    public:
        void attach(Action *a) override
        {
            actions.push_back(a);
        }
    
        void detach(Action *a) override
        {
            actions.remove(a);
        }
    
        void notify() override
        {
            for (auto act : actions)
            {
                (*act)();
            }
        }
    };
    
    // 具体的观察者,看股票的
    class StockObserver
    {
    private:
        string name;
        Subject *sub;
    
    public:
        StockObserver(string _name, Subject *_sub) : name(_name), sub(_sub)
        {
        }
    
        void StockObserverUpdate()
        {
            cout << name << " 收到消息:" << sub->event << endl;
            if (sub->event == "梁所长来了!")
            {
                cout << "我马上关闭股票,装做很认真工作的样子!" << endl;
            }
        }
    };
    
    // 具体的观察者,看NBA的
    class NBAObserver
    {
    private:
        string name;
        Subject *sub;
    
    public:
        NBAObserver(string _name, Subject *_sub) : name(_name), sub(_sub)
        {
        }
    
        void NBAObserverUpdate()
        {
            cout << name << " 收到消息:" << sub->event << endl;
            if (sub->event == "梁所长来了!")
            {
                cout << "我马上关闭股票,装做很认真工作的样子!" << endl;
            }
        }
    };
    
    int main()
    {
        // 创建通知者
        Subject *dwq = new Secretary();
    
        // 被观察的对象
        NBAObserver *xs = new NBAObserver("xiaoshuai", dwq);
        Action acA = bind(&NBAObserver::NBAObserverUpdate, xs);
        StockObserver *lm = new StockObserver("limin", dwq);
        Action acB = bind(&StockObserver::StockObserverUpdate, lm);
    
        // 加入观察者队列
        dwq->attach(&acA);
        dwq->attach(&acB);
    
        // 事件
        dwq->event = "去吃饭了!";
        // 通知
        dwq->notify();
        cout << endl;
    
        // 事件
        dwq->event = "梁所长来了!";
        // 通知
        dwq->notify();
        cout << endl;
    
        return 0;
    }
    
  • 相关阅读:
    【JAVA版本】websocket获取B站直播弹幕——基于直播开放平台
    springboot
    nodeJs 实现视频的转换(超详细教程)
    Linux性能优化
    神经网络和pid有什么区别,基于神经网络的pid控制
    一杯子三变:揭秘vue单页应用(spa)与内容动态加载的奥秘
    手绘地图深度解析:类型、风格、功能、价值、制作流程、智慧导览
    linux_三剑客(grep,sed,awk)
    一文总结你需要的OpenCV操作
    kmp:831. KMP字符串
  • 原文地址:https://blog.csdn.net/m0_47104421/article/details/139702648