您的当前位置:首页正文

C++观察者模式的实现

来源:华佗健康网

什么是观察者模式

        1.观察者模式是一种对象行为模式。它定义对象间的一种一对多的以来关系,当一个对象的状态发生改变时,所有依赖于他的对象都得到通知并被自动更新。

        2.在观察者模式中,主体是通知的发布者,他发出通知时并不需要知道谁是他的观察者,可以有任意数目的观察者订阅并接收通知。

        3.观察者模式(Observer)完美的将观察者和被观察的对象分离开。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。

        4.观察者模式不仅被广泛应用于软件界面元素之间的交互,在业务对象之间的交互、权限管理等方面也有广泛的应用。

观察者模式设计思路

        1.设定两个类,一个为观察者类,一个为被观察者类。

        2.观察者类中,定义一个对某个事件感兴趣的处理函数,一般也叫槽函数。

        3.被观察者类中,定义一个数据结构,用来保存观察者对哪一个事件id(信号)感兴趣,使用数据结构建立信号与对象之间的映射关系。

        4.被观察者类中,定义两个方法函数:

                4.1一个方法为:添加观察者与其感兴趣的事件id(信号)加入到容器之中。

                4.2另一个方法为:信号函数。通知事件函数执行逻辑:首先遍历容器之中,有没有感兴趣的事件id,如果有,则代表一系列的观察者对这个事件感兴趣,那么再次遍历观察者列表,让每一个观察者执行相应的槽函数。

代码演示

        定义信号接收者(观察者)类:

#include <iostream>
#include <map>
#include <list>
using namespace std;

//定义一个接收者的基类
class RecvBase
{
public:
    virtual void slots_function(int msgid) = 0;
    virtual ~RecvBase() = default;
};

//定义一个接收者的子类
class Recv : public RecvBase
{
private:
    string name;
public:
    Recv(string name) : name(name)
    { }

    //实现槽函数:
    void slots_function(int msgid) override
    {
        cout << "我是" << name;

        switch(msgid){
        case 1:
            cout << "收到信号1" << endl;
            break;
        case 2:
            cout << "收到信号2" << endl;
            break;
        case 3:
            cout << "收到信号3" << endl;
            break;
        }
    }
};

        定义信号发出者(被观察者)类:

        map,list为STL标准库中容器。

//定义一个信号的发出者
class Sender
{
private:
    //定义一个Map容器来保存信号id与所有对此id感兴趣的接收者
    //  (id, (recv1,recv2,...))
    map <int, list<RecvBase*>> senderMap;
    
public:
    //把所有对某信号id感兴趣的接收者的对象加入到list容器之中
    void addRecvFunction(int msgid, RecvBase* recv)
    {
        senderMap[msgid].push_back(recv);
    }

    //发出信号,并遍历所有感兴趣的接收者指针,让其执行相关的槽函数
    void signal(int msgid)
    {
        auto it = senderMap.find(msgid);
        for(RecvBase* p : it->second)
        {
            p->slots_function(msgid);
        }
    }
};

        主函数验证:

int main()
{
    //定义信号的发出者:
    Sender sender;
    //定义接收者对象:
    RecvBase* recv1 = new Recv("zhangsan");
    RecvBase* recv2 = new Recv("lisi");
    RecvBase* recv3 = new Recv("wangwu");

    //接收者与信号id绑定
    sender.addRecvFunction(1, recv1);   //将接收者1放入id=1的列表中
    sender.addRecvFunction(2, recv2);   //将接收者2放入id=2的列表中

    sender.addRecvFunction(3, recv1);   //将接收者1放入id=3的列表中
    sender.addRecvFunction(3, recv2);   //将接收者2放入id=3的列表中
    sender.addRecvFunction(3, recv3);   //将接收者3放入id=3的列表中

    //从终端循环输入信号:
    int msgid;
    for(;;)
    {
        cin >> msgid;   //cin为终端输入
        if(msgid == -1)
        {
            break;
        }
        sender.signal(msgid);   //发出信号
    }
    return 0;
}

        运行结果:

        

因篇幅问题不能全部显示,请点此查看更多更全内容