#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;
}