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

观察者模式-委托

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

非委托

#include <iostream>
#include <string>
#include <list>
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 <functional>
std::function<函数类型>

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

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

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

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

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

委托

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

  1. 去除了抽象观察者类
  2. 使用了C++的function+bind实现委托
#include <iostream>
#include <string>
#include <functional>
#include <list>
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;
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值