行为型模式:主要关注的是对象之间的通信
例如:一个对象调用另一个对象的成员 方法
目的:
观察者-监听者模式(发布-订阅模式)设计模式:主要关注的是对象的一对多的关系,也就是多个对象都依赖一个对象,当该对象的状态发生改变时,其它对象都能够接收到相应的通知。
应用场景:
例如一组数据(数据对象)就是一个对象,通过这一组数据可以生成曲线图(对象1),柱状图(对象2),圆饼图(对象3)。这些图像只是样子不一样,但是都基于同一个数据对象的改变而发生的变化。因此当数据对象的数据发生改变,其他三个对象就需要及时收到通知发生相应的响应
代码实现
#include<iostream>
#include<mutex>
#include<memory>
#include<unordered_map>
#include<list>
using namespace std;//观察者抽象类
class Observer
{
public://处理消息的接口virtual void handle(int msgid) = 0;
};//第一个观察者实例
class Observer1:public Observer
{
public://处理消息的接口void handle(int msgid){switch (msgid){case 1:cout << "Observer1 recv 1 msg" << endl;break;case 2:cout << "Observer1 recv 2 msg" << endl;break;default:cout << "Observer1 recv unknow msg" << endl;break;}}
};
class Observer2 :public Observer
{
public://处理消息的接口void handle(int msgid){switch (msgid){case 2:cout << "Observer2 recv 2 msg" << endl;break;default:cout << "Observer2 recv unknow msg" << endl;break;}}
};
class Observer3 :public Observer
{
public://处理消息的接口void handle(int msgid){switch (msgid){case 1:cout << "Observer3 recv 1 msg" << endl;break;case 3:cout << "Observer3 recv 3 msg" << endl;break;default:cout << "Observer3 recv unknow msg" << endl;break;}}
};class Subject//需要存储每一个观察者感兴趣的事件
{
public:void addObserver(Observer*obser,int msgid){//subMap[msgid].push_back(obser);auto it = subMap.find(msgid);if (it != subMap.end()){it->second.push_back(obser);}else{list<Observer*>lis;lis.push_back(obser);subMap.insert({ msgid,lis });}}//主题检测发生改变,通知相应的观察者对象处理事件void dispath(int msgid){auto it = subMap.find(msgid);if (it != subMap.end()){for (Observer* pobser : it->second){pobser->handle(msgid);}}}
private://因为对一个消息感兴趣的可能是多个观察者所以使用list存储观察者unordered_map<int, list<Observer*>>subMap;};
int main()
{Subject sub;Observer* p1 = new Observer1();Observer* p2 = new Observer2();Observer* p3 = new Observer3();sub.addObserver(p1, 1); sub.addObserver(p1, 2);sub.addObserver(p2, 2);sub.addObserver(p3, 1);sub.addObserver(p3, 3);int msgid = 0;for (;;){cout << "请输入消息id: " << endl;cin >> msgid;if (msgid == -1){break;}sub.dispath(msgid);}return 0;
}