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:";
    }

}
相关推荐
杨充13 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充13 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充13 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充13 小时前
2.面向对象的特性
设计模式
杨充13 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充13 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充13 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯16 小时前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式