目录
一.观察者模式
观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
如何解决:使用面向对象技术,可以将这种依赖关系弱化。
关键代码:在抽象类里有一个 ArrayList 存放观察者们。
应用实例:假设现在有一名男子怀疑自己被戴了绿帽子,但是他又没有证据,于是他花钱雇佣了一位私家侦探去调查他的老婆,并告诉这位私家侦探如果一有什么动静发生,就立马通知他,好让他采取行动。在这个例子中这位男子就是监听者,而这位私家侦探就是观察者,观察者所要做的事情就是观察某一事件是否发生,如果事件发生了就去通知监听者,而监听者所要做的就是处理事件。
观察者和监听者之间的关系(多对多):
- 多个观察者可以为同一个监听者服务。
- 一个观察者可以为多个监听者服务。
二.代码实现
#include<iostream>
#include<map>
#include<vector>
class Listener
{
public:
Listener(std::string name)
:mname(name) {}
virtual void handleMessage(int message) = 0;
protected:
std::string mname;
};
class Listener1 : public Listener
{
public:
Listener1(std::string name) :Listener(name) {}
void handleMessage(int message)
{
switch (message)
{
case 1:
std::cout << mname << " : 1 " << "has been solved! " << std::endl;
break;
case 2:
std::cout << mname << " : 2 " << "has been solved! " << std::endl;
break;
default:
std::cout << mname << " no interested this message!" << std::endl;
break;
}
}
};
class Listener2 : public Listener
{
public:
Listener2(std::string name) :Listener(name) {}
void handleMessage(int message)
{
switch (message)
{
case 2:
std::cout << mname << " : 2 " << "has been solved! " << std::endl;
break;
case 3:
std::cout << mname << " : 3 " << "has been solved! " << std::endl;
break;
default:
std::cout << mname << " no interested this message!" << std::endl;
break;
}
}
};
class Listener3 : public Listener
{
public:
Listener3(std::string name) :Listener(name) {}
void handleMessage(int message)
{
switch (message)
{
case 1:
std::cout << mname << " : 1 " << "has been solved! " << std::endl;
break;
case 3:
std::cout << mname << " : 3 " << "has been solved! " << std::endl;
break;
default:
std::cout << mname << " no interested this message!" << std::endl;
break;
}
}
};
class Oberseve
{
public:
void notify(int message)//某一事件发生;
{
std::map<int, std::vector<Listener*>>::iterator fit = mymap.find(message);
if (fit != mymap.end())//有感兴趣的监听者
{
std::vector<Listener*>::iterator it = fit->second.begin();//vector迭代器
while (it != fit->second.end())
{
//消息通知 调用对方的接口
(*it)->handleMessage(message);
it++;
}
}
else//没感兴趣的监听者
{
std::cout << "no listener interested this message!" << std::endl;
}
}
void registerMessage(int message, Listener* pl)//让观察者观察某一事件
{
std::map<int, std::vector<Listener*>>::iterator fit = mymap.find(message);
if (fit != mymap.end())//找到了 该事件已经注册 插入监听者集合
{
fit->second.push_back(pl);
}
else//没找到 map 插入一个关系
{
std::vector<Listener*> vec;
vec.push_back(pl);
mymap[message] = vec;
}
}
private:
std::map<int, std::vector<Listener*>> mymap;//事件 监听者
};
int main()
{
Listener1 l1("listener1");
Listener2 l2("listener2");
Listener3 l3("listener3");
Oberseve ob;
ob.registerMessage(1, &l1);//表示1号监听者对1号事件感兴趣
ob.registerMessage(2, &l1);//表示2号监听者对1号事件感兴趣
ob.registerMessage(2, &l2);//表示2号监听者对2号事件感兴趣
ob.registerMessage(3, &l2);//表示3号监听者对2号事件感兴趣
ob.registerMessage(1, &l3);//表示1号监听者对3号事件感兴趣
ob.registerMessage(3, &l3);//表示3号监听者对3号事件感兴趣
ob.notify(1);//事件1发生
ob.notify(2);//事件2发生
ob.notify(3);//事件3发生
ob.notify(4);//事件4发生
return 0;
}
在上述代码中,Listener类中的handleMessage(int message)函数,代表处理事件函数,即此时某监听者感兴趣的事件message发生了,监听者会调用这个函数来进行相应的处理。在本例中,我们规定一号监听者listener1只对事件1和事件2感兴趣,二号监听者只对事件2和事件3感兴趣,三号监听者只对事件1和事件3感兴趣。
前面我们讲到过一个监听者可能对多个事件感兴趣,为了描述这一特征,我们使用单映射容器map来存放某一事件和对这一事件感兴趣的监听者,我们用map容器中的键(key)来表示某一事件,用值(value)来表示对这一事件感兴趣的监听者,考虑到监听者可能有多个,我们在用vector容器来存放对某一事件感兴趣的监听者,即这里map容器中的键值对为key:int->value:vector,而vector中存放监听者,即
std::map<int, std::vector<Listener*>> mymap};//事件 监听者
在观察者类Oberseve中有两个成员函数,分别是void notify(int message) 和 void registerMessage(int message, Listener* pl)。我们首先来看
void notify(int message)//某一事件发生;
{
std::map<int, std::vector<Listener*>>::iterator fit = mymap.find(message);
if (fit != mymap.end())//有感兴趣的监听者
{
std::vector<Listener*>::iterator it = fit->second.begin();//vector迭代器
while (it != fit->second.end())
{
//消息通知 调用对方的接口
(*it)->handleMessage(message);
it++;
}
}
else//没感兴趣的监听者
{
std::cout << "no listener interested this message!" << std::endl;
}
}
这个函数代表此时message这个事件发生了,这是观察者要干的第一件事就是判断是否有监听者对此时发生的这个事件message感兴趣,于是我们首先使用find函数在map容器中查找是否有键(key)== message的数据。如果有,说明有对这个事件感兴趣的观察者,接着我们就对这个事件感兴趣的所有监听者发送信息(因为对 某一事件感兴趣的监听者可能有多个),也就是调用handleMessage这个借口。如果没有对这个事件感兴趣的监听者(即map容器中不存在键(key)== message 的数据),就不做任何处理。
void registerMessage(int message, Listener* pl)//让观察者观察某一事件
{
std::map<int, std::vector<Listener*>>::iterator fit = mymap.find(message);
if (fit != mymap.end())//找到了 该事件已经注册 插入监听者集合
{
fit->second.push_back(pl);
}
else//没找到 map 插入一个关系
{
std::vector<Listener*> vec;
vec.push_back(pl);
mymap[message] = vec;
}
}
registerMessage这个函数代表让观察者观察某一事件,并且表明哪些监听者对这个事件感兴趣,假设现在我们给定了某一事件message,我们首先要做的就是判断观察者是否已经观察了这个事件,即判断当map容器中是否存在键(key) == message 的数据,如果不存在就将这个事件插入。如果存在就说明观察者已经观察了这一事件,即map容器中已经存在键(key) == message 的数据,那么就将其他对这个事件感兴趣的监听者插入(因为可能有多个监听者对同一事件感兴趣的可能)。