介绍
观察者模式主要关注于对象的一对多关系,其中多个对象都依赖于一个对象,当该对象的状态发生改变时,其余对象都能接收到相应的通知。
如,现在有
- 一个数据对象
- 三个画图对象,分别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:";
}
}