1. 程式人生 > >C++釋出訂閱者模式demo

C++釋出訂閱者模式demo

#ifndef _OBSERVER_H_  
#define _OBSERVER_H_  
  
#include <map>  
#include <mutex>  
  
using namespace std;  
  
class Msg  
{  
public:  
    virtual int GetMsgID() = 0;  
  
    virtual void* GetMsg() = 0;  
  
};  
  
class MsgContainer;  
  
class Subscriber  
{  
public:  
    virtual void subscribe(MsgContainer *pMsgContainer, int MsgID);  
  
    virtual void unsubscribe(MsgContainer *pMsgContainer, int MsgID);  
  
    virtual void handleMsg(Msg *msg) = 0;  
};  
  
class MsgContainer  
{  
public:  
    virtual void add_subscriber(Subscriber *pSubscriber, int MsgID);  
  
    virtual void remove_subscriber(Subscriber *pSubscriber, int MsgID);  
  
    virtual void receiveMsg(Msg *msg);  
  
protected:  
    virtual void notify(Msg *msg);  
  
private:  
    multimap<int, Subscriber*> m_subscriber;  
    mutex m_mutex;  
};  
  
class Publisher  
{  
public:  
    virtual void sendMsg(MsgContainer *pMsgContainer, Msg *msg);  
};  
  
class MsgImp :public Msg  
{  
public:  
    MsgImp(int MsgID, void *Msgfield);  
  
    virtual ~MsgImp();  
  
    virtual int GetMsgID();  
  
    virtual void* GetMsg();  
  
private:  
    int m_MsgID;  
  
    void *m_Msgfield;  
};  
  
class SubscriberImp :public Subscriber  
{  
public:  
    SubscriberImp();  
  
    virtual ~SubscriberImp();  
  
    virtual void handleMsg(Msg *msg);  
private:  
    void *m_expext_field;  
};  
  
class SubscriberImp2 :public Subscriber  
{  
public:  
    SubscriberImp2();  
    virtual ~SubscriberImp2();  
  
    virtual void handleMsg(Msg *msg);  
private:  
    void *m_expext_field;  
};  
  
class PublisherImp :public Publisher  
{  
public:  
    PublisherImp();  
  
    virtual ~PublisherImp();  
};  
  
#endif  

#include "observer.hpp"  
#include <iostream>  
  
using namespace std;  
  
  
MsgImp::MsgImp(int MsgID, void *Msgfield)  
{  
    m_MsgID = MsgID;  
    m_Msgfield = Msgfield;  
}  
  
MsgImp::~MsgImp()  
{  
  
}  
  
int MsgImp::GetMsgID()  
{  
    return m_MsgID;  
}  
  
void * MsgImp::GetMsg()  
{  
    return m_Msgfield;  
}  
  
void Subscriber::subscribe(MsgContainer *pMsgContainer, int MsgID)  
{  
    pMsgContainer->add_subscriber(this, MsgID);  
}  
  
void Subscriber::unsubscribe(MsgContainer *pMsgContainer, int MsgID)  
{  
    pMsgContainer->remove_subscriber(this, MsgID);  
}  
  
SubscriberImp::SubscriberImp()  
{  
  
};  
  
SubscriberImp::~SubscriberImp()  
{  
    delete m_expext_field;  
};  
  
void SubscriberImp::handleMsg(Msg *msg)  
{  
    m_expext_field = msg->GetMsg();  
      
    cout << __func__ << ": this is the SubscriberImp1..." << endl;  
    cout <<__func__ << ": the MsgID is " << msg->GetMsgID() << endl;  
    cout <<__func__ << ": " << (char *) msg->GetMsg() << ", SubscriberImp1 handle the msg"<<endl;  
}  
  
SubscriberImp2::SubscriberImp2()  
{  
  
};  
  
SubscriberImp2::~SubscriberImp2()  
{  
    delete m_expext_field;  
};  
  
void SubscriberImp2::handleMsg(Msg *msg)  
{  
    m_expext_field = msg->GetMsg();  

    cout << __func__ << ": this is the SubscriberImp2..." << endl;  
    cout <<__func__ << ": the MsgID is " << msg->GetMsgID() << endl;  
    cout <<__func__ << ": " << (char *) msg->GetMsg() << ", SubscriberImp2 handle the msg"<<endl;  
}  
  
void MsgContainer::add_subscriber(Subscriber *pSubscriber, int MsgID)  
{  
    lock_guard<mutex> guard(m_mutex);  
  
    if (m_subscriber.empty())  
    {  
        m_subscriber.insert(make_pair(MsgID, pSubscriber));  
    }  
  
    bool isExist = false;  
    map<int, Subscriber*>::iterator it = m_subscriber.lower_bound(MsgID);  
    while (it != m_subscriber.upper_bound(MsgID))  
    {  
        if (it->second == pSubscriber)  
            isExist = true;  
        it++;  
    }  
    if (!isExist)  
    {  
        m_subscriber.insert(make_pair(MsgID, pSubscriber));  
    }  
}  
  
void MsgContainer::remove_subscriber(Subscriber *pSubscriber, int MsgID)  
{  
    lock_guard<mutex> guard(m_mutex);  
  
    if (m_subscriber.empty())  
    {  
        return;  
    }  
  
    multimap<int, Subscriber*>::iterator it = m_subscriber.lower_bound(MsgID);  
    while (it != m_subscriber.upper_bound(MsgID))  
    {  
        if (it->second == pSubscriber)  
        {  
            m_subscriber.erase(it);  
            break;  
        }  
        it++;  
    }  
}  
  
void MsgContainer::notify(Msg *msg)  
{  
    multimap<int, Subscriber*>::iterator it = m_subscriber.lower_bound(msg->GetMsgID());  
    for (; it != m_subscriber.upper_bound(msg->GetMsgID()); it++)  
    {  
        it->second->handleMsg(msg);  
    }  
}  
  
void MsgContainer::receiveMsg(Msg *msg)  
{  
    lock_guard<mutex> guard(m_mutex);  
  
    this->notify(msg);  
}  
  
  
void Publisher::sendMsg(MsgContainer *pMsgContainer, Msg *msg)  
{  
    pMsgContainer->receiveMsg(msg);  
}  
  
PublisherImp::PublisherImp(){};  
PublisherImp::~PublisherImp(){};  

#include "observer.hpp"  
#include <iostream>  
  
using namespace std;  
  
int main()  
{  
    Subscriber *subscriber = NULL;  
    MsgContainer *msgcontainer = new MsgContainer();  
    Msg *msg = NULL;  
    Publisher *publisher = NULL;  
  
    char *msgfield = NULL;  
  
    subscriber = new SubscriberImp();  
    subscriber->subscribe(msgcontainer, 2);  
  
    Subscriber *subscriber2 = NULL;  
    subscriber2 = new SubscriberImp2();  
    subscriber2->subscribe(msgcontainer, 2);  
  
	std::cout << "-----------------------------------------------" << std::endl;
    msgfield = "publisher: the publisher send this msg";  
    msg = new MsgImp(2, msgfield);  
  
    publisher = new PublisherImp();  
    publisher->sendMsg(msgcontainer,msg);  
  
    subscriber2->unsubscribe(msgcontainer,2);  

	std::cout << "-----------------------------------------------" << std::endl;
    msgfield = "publisher: the publisher send this msg2";  
    msg = new MsgImp(2, msgfield);  
    publisher = new PublisherImp();  
    publisher->sendMsg(msgcontainer, msg);  
  
    return 0;  
}