1. 程式人生 > >設計模式——觀察者監聽者模式

設計模式——觀察者監聽者模式

**基於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++共享物件的執行緒安全問題,其它執行緒安全管不了→_→