行为型模式:主要关注的是对象之间的通信
例如:一个对象调用另一个对象的成员 方法
观察者-监听者模式(发布-订阅模式)设计模式:主要关注的是对象的一对多的关系,也就是多个对象都依赖一个对象,当该对象的状态发生改变时,其它对象都能够接收到相应的通知。
例如一组数据(数据对象)就是一个对象,通过这一组数据可以生成曲线图(对象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;
}