**基於map的觀察者監聽者設計模式
《1》回調函數
《2》MVC框架**(如下圖所示)
觀察者通過搜索得到都有誰對這個事件感興趣,就告訴那些對該事件感興趣的監聽者去處理該事件,很明顯一個事件和對該事件感興趣的監聽者是鍵值映射關係,故使用map.
版本一:監聽者和觀察者在同一個線程中
#include <iostream>
#include <memory>
#include <map>
#include <vector>
#include <string>
using namespace std;
class Listener
{
public:
Listener(string name):_name(name){}
virtual void handleMessage(int msgid)=0;
string _name;
};
class Listener1:public Listener
{
public:
Listener1(string name):Listener(name){}
void handleMessage(int msgid)
{
cout<<_name<<" ";
switch(msgid)
{
case 0:
cout<<" handle 0 msgid!"<<endl;
break;
case 1:
cout<<" handle 1 msgid!"<<endl;
break;
default:
cout<<" handle invalid msgid!"<<endl;
break;
}
}
};
class Listener2:public Listener
{
public:
Listener2(string name):Listener(name){}
void handleMessage(int msgid)
{
cout<<_name<<" ";
switch(msgid)
{
case 0:
cout<<" handle 0 msgid!"<<endl;
break;
case 2:
cout<<" handle 2 msgid!"<<endl;
break;
default:
cout<<" handle invalid msgid!"<<endl;
break;
}
}
};
class Listener3:public Listener
{
public:
Listener3(string name):Listener(name){}
void handleMessage(int msgid)
{
cout<<_name<<" ";
switch(msgid)
{
case 1:
cout<<" handle 1 msgid!"<<endl;
break;
case 3:
cout<<" handle 3 msgid!"<<endl;
break;
default:
cout<<" handle invalid msgid!"<<endl;
break;
}
}
};
class Observer
{
public:
void registerMsg(Listener *plistener,int msgid)
{
map<int,vector<Listener*>>::iterator it = _obserMap.find(msgid);
if(it == _obserMap.end())
{
vector<Listener*> vec;
vec.push_back(plistener);
_obserMap.insert(make_pair(msgid,vec));
}else
{
it->second.push_back(plistener);
}
}
void dispatchMsg(int msgid)
{
map<int,vector<Listener*>>::iterator it = _obserMap.find(msgid);
if(it != _obserMap.end())
{
vector<Listener*>::iterator vit = it->second.begin();
for(;vit != it->second.end();++vit)
{
(*vit)->handleMessage(msgid);
}
}
}
private:
map<int,vector<Listener*>> _obserMap;
};
int main()
{
Listener1 *p1 = new Listener1("Listener1");
Listener2 *p2 = new Listener2("Listener2");
Listener3 *p3 = new Listener3("Listener3");
Observer obser;
obser.registerMsg(p1,0);
obser.registerMsg(p1,1);
obser.registerMsg(p2,0);
obser.registerMsg(p2,2);
obser.registerMsg(p3,1);
obser.registerMsg(p3,3);
int msgid = 0;
while(true)
{
cout<<"msgid:";
cin>>msgid;
obser.dispatchMsg(msgid);
}
return 0;
}
版本二:有時在高併發模式下,監聽者和觀察者不在同一個線程中,共享的對象不是線程安全的,因爲在另一個線程中訪問另一個線程的對象,並不知道對象是否存活,因此引入智能指針。
#include <iostream>
#include <memory>
#include <map>
#include <vector>
#include <string>
using namespace std;
class Listener
{
public:
Listener(string name):_name(name){}
virtual void handleMessage(int msgid)=0;
string _name;
};
class Listener1:public Listener
{
public:
Listener1(string name):Listener(name){}
void handleMessage(int msgid)
{
cout<<_name<<" ";
switch(msgid)
{
case 0:
cout<<" handle 0 msgid!"<<endl;
break;
case 1:
cout<<" handle 1 msgid!"<<endl;
break;
default:
cout<<" handle invalid msgid!"<<endl;
break;
}
}
};
class Listener2:public Listener
{
public:
Listener2(string name):Listener(name){}
void handleMessage(int msgid)
{
cout<<_name<<" ";
switch(msgid)
{
case 0:
cout<<" handle 0 msgid!"<<endl;
break;
case 2:
cout<<" handle 2 msgid!"<<endl;
break;
default:
cout<<" handle invalid msgid!"<<endl;
break;
}
}
};
class Listener3:public Listener
{
public:
Listener3(string name):Listener(name){}
void handleMessage(int msgid)
{
cout<<_name<<" ";
switch(msgid)
{
case 1:
cout<<" handle 1 msgid!"<<endl;
break;
case 3:
cout<<" handle 3 msgid!"<<endl;
break;
default:
cout<<" handle invalid msgid!"<<endl;
break;
}
}
};
class Observer
{
public:
void registerMsg(weak_ptr<Listener>plistener,int msgid)//傳弱智能指針
{
map<int,vector<weak_ptr<Listener>>>::iterator it = _obserMap.find(msgid);
if(it == _obserMap.end())
{
vector<weak_ptr<Listener>> vec;
vec.push_back(plistener);
_obserMap.insert(make_pair(msgid,vec));
}else
{
it->second.push_back(plistener);
}
}
void dispatchMsg(int msgid)
{
map<int,vector<weak_ptr<Listener>>>::iterator it = _obserMap.find(msgid);
if(it != _obserMap.end())
{
vector<weak_ptr<Listener>>::iterator vit = it->second.begin();
for(;vit != it->second.end();++vit)
{
//通過弱智能指針觀察對象的引用計數是否爲0,進而觀察對象的存活
//訪問對象時需要先將弱智能指針提升爲強智能指針,
shared_ptr<Listener> p = (*vit).lock();
if(p != NULL)
{
p->handleMessage(msgid);
}
}
}
}
private:
map<int,vector<weak_ptr<Listener>>> _obserMap;//使用弱智能指針
};
int main()
{
//定義的時候用強智能指針
shared_ptr<Listener> p1(new Listener1("Listener1"));
shared_ptr<Listener> p2(new Listener2("Listener2"));
shared_ptr<Listener> p3(new Listener3("Listener3"));
Observer obser;
obser.registerMsg(p1,0);
obser.registerMsg(p1,1);
obser.registerMsg(p2,0);
obser.registerMsg(p2,2);
obser.registerMsg(p3,1);
obser.registerMsg(p3,3);
int msgid = 0;
while(true)
{
cout<<"msgid:";
cin>>msgid;
obser.dispatchMsg(msgid);
}
return 0;
}
注意:在這裏引入智能指針只是解決了C++共享對象的線程安全問題,其它線程安全管不了→_→