設計模式——觀察者監聽者模式
阿新 • • 發佈:2019-02-13
**基於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++共享物件的執行緒安全問題,其它執行緒安全管不了→_→