c++设计模式之观察者模式(发布-订阅模式)

介绍

观察者模式主要关注于对象的一对多关系 ,其中多个对象都依赖于一个对象,当该对象的状态发生改变时,其余对象都能接收到相应的通知。

如,现在有

  • 一个数据对象
  • 三个画图对象,分别wield曲线图、柱状图、饼状图三个对象
  • 这三个画图对象都依赖于数据对象的数据
  • 而观察者模式要做的是,当数据对象的数据发生改变时,依赖数据对象的曲线图、柱状图、饼状图对象的图形都要及时作出改变

案例

  • 定义三个obsever对象,和一个subject对象
  • 每个observer对象都对subject对象的一个或者多个消息感兴趣
  • 当subject对象的数据状态发生改变时,应及时通知对应的观察者,并作出改变

observer类

cpp 复制代码
//观察者抽象类
class Observer
{
public:
    //观察者消息处理函数
    virtual void handler(int msgid)=0;
};

//第一个观察者实例
class Observer1:public Observer
{
public:
    void handler(int msgid)
    {
    //第一个观察者对消息1和消息2感兴趣,
    //当消息1或者消息2的状态发生改变时,该观察者作出对应的响应
        switch(msgid)
        {
            case 1:
                cout<<"observer1 recv msg 1"<<endl;
                break;
            case 2:
                cout<<"observer1 recv msg 2"<<endl;
                break;
            default:
                cout<<"oberver1 recv unknow msg!"<<endl;
                break;
        }
    }
};

//第二个观察者实例
class Observer2:public Observer{
public:
    void handler(int msgid)
    {
        switch(msgid)
        {

            case 2:
                cout<<"observer2 recv msg 2"<<endl;
                break;
            default:
                cout<<"oberver2 recv unknow msg!"<<endl;
                break;
        }
    }
};

//第三个观察者实例
class Observer3:public Observer{
public:
    void handler(int msgid)
    {
        switch(msgid)
        {
            case 1:
                cout<<"observer3 recv msg 1"<<endl;
                break;
            case 3:
                cout<<"observer3 recv msg 3"<<endl;
                break;
            default:
                cout<<"oberver3 recv unknow msg!"<<endl;
                break;
        }       
    }
};

subject类

cpp 复制代码
//主题类
class Subject
{
public:
    //将观察者及其所感兴趣的消息添加到map中
    void addOberver(Observer* obser,int msgid)
    {
        _subMap[msgid].push_back(obser);
    }

    //检测到感兴趣的消息发生了改变,就及时通知对应的观察者
    void dispatch(int msgid)
    {
        auto it=_subMap.find(msgid);//寻找该消息对应的观察者
        if(it!=_subMap.end())
        {
            for(Observer* obser:it->second)
            {
                obser->handler(msgid);//将发生的消息发送给对应的观察者
            }
        }
    }
private:
    //int:消息id;list<Observer*>:对该消息感兴趣的观察者
    /*即每一个消息都有其对应感兴趣的观察者*/
    unordered_map<int,list<Observer*>> _subMap;
};

测试

cpp 复制代码
void test()
{
    Observer* p1=new Observer1;
    Observer* p2=new Observer2;
    Observer* p3=new Observer3;

    Subject sub;
    //注册观察者及其感兴趣的消息
    //第一个观察者对消息1和消息2感兴趣
    sub.addOberver(p1,1);
    sub.addOberver(p1,2);
    //第二个观察者对消息2感兴趣
    sub.addOberver(p2,2);
    //第三个观察者对消息1和消息3感兴趣
    sub.addOberver(p3,1);
    sub.addOberver(p3,3);

    int msgid;
    cout<<"输入消息id:";
    while(cin>>msgid)
    {
        if(msgid==-1)
            break;
        sub.dispatch(msgid);
        cout<<"输入消息id:";
    }

}
相关推荐
Adellle6 分钟前
设计模式指南 (Java 版) ㊁
java·开发语言·设计模式
是2的10次方啊1 小时前
设计模式与生活⑱:工资还没焐热,账单已经凑成一摞
设计模式
百思不得小李14 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
爱你真是太好了17 小时前
上下文组成以及如何压缩
设计模式
freejackman21 小时前
【工程化】从“单兵作战”到“多引擎架构”:基于门面模式的重构实战
大数据·数据库·hive·sql·测试工具·设计模式·架构
Java成神之路-1 天前
从 if-else 到优雅解耦:策略 / 适配器 / 组合模式全流程实战
设计模式
是2的10次方啊1 天前
设计模式与生活⑰:空腹体检,单子领着人走
设计模式
是2的10次方啊2 天前
设计模式与生活⑯:天冷了,出门这身得一层层配
设计模式
心若自由何处是束缚3 天前
适配器模式:从原理到实战的完整指南
设计模式·适配器模式
是2的10次方啊3 天前
设计模式与生活⑮:看到哪儿了,得有个地方替你记着
设计模式