介绍
观察者模式主要关注于对象的一对多关系,其中多个对象都依赖于一个对象,当该对象的状态发生改变时,其余对象都能接收到相应的通知。
如,现在有
- 一个数据对象
- 三个画图对象,分别wield曲线图、柱状图、饼状图三个对象
- 这三个画图对象都依赖于数据对象的数据
- 而观察者模式要做的是,当数据对象的数据发生改变时,依赖数据对象的曲线图、柱状图、饼状图对象的图形都要及时作出改变
案例
- 定义三个obsever对象,和一个subject对象
- 每个observer对象都对subject对象的一个或者多个消息感兴趣
- 当subject对象的数据状态发生改变时,应及时通知对应的观察者,并作出改变
observer类
//观察者抽象类
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类
//主题类
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;
};
测试
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:";}}