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

**基於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++共享對象的線程安全問題,其它線程安全管不了→_→

發佈了49 篇原創文章 · 獲贊 16 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章