今天看了gof的设计模式的观察者模式一章,仿造sip协议中的订阅和发布的相关思路,仿造gof的框架结构写了如下c++代码。
此代码仅仅是对观察者模式的一个简单实现,结构不算复杂。
观察者模式定义了对象之间的一对多依赖关系,当一个对象的状态发生改变的时候,所有依赖他的对象都得到通知并被自动更新。以QQ举例,你和你的qq好友时一族相互的依赖对象,当你的好友上线了,你可以看到你的好友上线的状态,当他离线了,你可以看到他的离线信息,当他更改了名字,你也可以看到他更改了名字。针对这种情况,你自身就是一个观察者,而你的好友是被观察的对象,一般称之为目标对象。你可能会问你你上线下线,你的好友也会知道呀,对的,这种情况下你自身就是一个目标对象,而你的好友就转换成了观察者了。也就是说观察者和目标对象只是在一种通知场景中的依赖关系的命名逻辑,观察者同时也可以是目标对象。下面的代码就是以这种策略思想实现的。
以观察者模式的架构实现sip用户发布和订阅的相关框架,注意:和sip协议本身没有任何关系。由于一个用户既可以订阅他人的状态信息,同时他自身又可以被别人订阅,也就是说他可以既是观察者,又是目标(被观察者).因此我采用c++的多重继承,既继承了Observer观察者类,又继承了Subject目标类。当然如果没有多重继承机制的语言,可以直接在一个类中定义观察者和目标的所有方法。
Observer观察者,或者称之为订阅者。有一个私有成员保持着他所观察的目标对象集合,在当前的代码中没有用处,为了后续扩展使用。
Subject目标,被观察对象,或者称之为被订阅对象。有一个似有成员保存着所有观察他的观察者集合,当此目标状态改变时候,会向这个集合中的所有观察者发送通知消息(有一个前提,必须是订阅了他的状态的用户才会收到此通知)。
SipUser:sip用户,继承于Observer和Subject,有两个私有属性,姓名和在线状态,当用户的姓名或者状态改变的时候,会向所有订阅姓名或者状态信息的观察者发送通知消息,打印相应的改变。
一个主要类型:观察者希望订阅目标的哪一个方面,现在可以选择姓名或者在线状态。如果订阅姓名,那么当姓名改变的时候,会向此观察者发送信息,如果没有订阅状态,那么时当状态改变的时候是不会向观察者发送状态改变的信息的。
ObserverAndInterst保存者观察者的指针,以及观察的类型
就是一个int变量,采用位操作(一个位代表一种类型,现在仅仅使用两位,姓名和在线状态)表明用户希望观察的类型。
#define INTERST_ASPECTS_NAME 1<<1
#define INTERST_ASPECTS_STATE 1<<2
#define INTERST_ASPECTS_ALL 0xFFFF
typedefint InterestAspects;//位操作,表明观察者感兴趣的类型
class Observer;
typedefstruct ObserverAndInterst//结构体,作为观察者和其感兴趣的一种类型的绑定
{
Observer* observer;
InterestAspects interst;
}ObserverAndInterst;
#define __PatternObserver__Observer__
#include <iostream>
#include <list>
#include "PatternObserverType.h"
using namespace std;
class Subject;
typedeflist<Subject*> ListSubject;
class Observer
{
public:
virtual ~Observer();
virtualvoid Update(Subject* theChangedSubject,InterestAspects intersts) =0;
//of course if only One Subject, just in consturct function
//add subscribe, want to subscribe s
virtualvoid AddSubjects(Subject *s,InterestAspects intersts);
//remove subscribe
virtualvoid RemoveSubjects(Subject* s,InterestAspects intersts);
protected:
Observer();
private:
ListSubject* m_listSubjects;
};
#endif /* defined(__PatternObserver__Observer__) */
#ifndef __PatternObserver__Subject__
#define __PatternObserver__Subject__
#include <iostream>
#include <list>
#include "PatternObserverType.h"
using namespace std;
class Observer;
typedef list<ObserverAndInterst> ListObserver;
class Subject
{
public:
virtual ~Subject();
virtualvoid Attach(Observer*,InterestAspects);
virtualvoid Detach(Observer*,InterestAspects);
virtualvoid Notify(InterestAspects);
protected:
Subject();
private:
ListObserver *m_listObservers;
};
#endif /* defined(__PatternObserver__Subject__) */
#ifndef __PatternObserver__SipUser__
#define __PatternObserver__SipUser__
#include <iostream>
#include "Observer.h"
#include "Subject.h"
/*
0: OffLine
1: OnLine
2: Busy
*/
class SipUser : publicObserver,public Subject
{
private:
string m_strName;
int m_nState;
public:
SipUser():m_strName("UnKnown"),m_nState(0){}
SipUser(string name,int state =0):m_strName(name),m_nState(state){}
~SipUser(){}
//for Subject. Changed State or Name to Notify
void SetState(int state){
if (m_nState != state) {
std::cout<<m_strName <<" State Change:-------"<<endl;
m_nState = state;
Notify(INTERST_ASPECTS_STATE);
std::cout<<endl;
}
}
int GetState(void){
returnm_nState;
}
void SetName(conststring& name){
if(m_strName.compare(name) !=0){
std::cout<<m_strName <<" Name Change:-------"<<endl;
m_strName = name;
Notify(INTERST_ASPECTS_NAME);
std::cout<<endl;
}
}
string GetName(void){
returnm_strName;
}
//for Observer
//AddSubject, RemoveSubject
void Update(Subject* theChangedSubject,InterestAspects intersts);
};
#endif /* defined(__PatternObserver__SipUser__) */
#include <iostream>
#include "SipUser.h"
#include "Observer.h"
#include "Subject.h"
#include "unistd.h"
#include "PatternObserverType.h"
int main(int argc,constchar * argv[])
{
// insert code here...
//std::cout << "Hello, World!\n";
SipUser A("A",0);
SipUser B("B",0);
SipUser C("C",0);
SipUser D("D",0);
SipUser E("E",0);
E.AddSubjects(&A,INTERST_ASPECTS_ALL);
C.AddSubjects(&A,INTERST_ASPECTS_STATE);
C.AddSubjects(&B,INTERST_ASPECTS_STATE);
D.AddSubjects(&B,INTERST_ASPECTS_STATE);
A.AddSubjects(&E,INTERST_ASPECTS_STATE);
B.AddSubjects(&E,INTERST_ASPECTS_STATE);
B.AddSubjects(&C,INTERST_ASPECTS_STATE);
E.AddSubjects(&C,INTERST_ASPECTS_STATE);
A.AddSubjects(&D,INTERST_ASPECTS_STATE);
C.AddSubjects(&D,INTERST_ASPECTS_STATE);
A.SetState(1);
B.SetState(2);
C.SetState(3);
D.SetState(4);
E.SetState(5);
A.SetName("AA");
E.RemoveSubjects(&A,INTERST_ASPECTS_ALL);
A.SetName("A");
while (1) {
sleep(3);
}
return0;
}
//
// Observer.cpp
// PatternObserver
#include "Observer.h"
#include "Subject.h"
#include <assert.h>
#include "PatternObserverType.h"
Observer::Observer()
{
m_listSubjects =newListSubject();
assert(m_listSubjects !=NULL);
}
Observer::~Observer()
{
if(m_listSubjects)
{
delete m_listSubjects;
m_listSubjects =NULL;
}
}
voidObserver::AddSubjects(Subject *s,InterestAspects intersts)
{
if(m_listSubjects && s){
m_listSubjects->push_back(s);
s->Attach(this, intersts);
}
}
voidObserver::RemoveSubjects(Subject* s,InterestAspects intersts)
{
if(m_listSubjects && s){
m_listSubjects->remove(s);
s->Detach(this, intersts);
}
}
//
// Subject.cpp
// PatternObserver
#include "Subject.h"
#include "Observer.h"
#include <assert.h>
Subject::Subject()
{
m_listObservers =newlist<ObserverAndInterst>();
assert(m_listObservers !=NULL);
}
Subject::~Subject()
{
if(m_listObservers){
deletem_listObservers;
m_listObservers =NULL;
}
}
void Subject::Attach(Observer* ob,InterestAspects interst)
{
if (m_listObservers && ob) {
ObserverAndInterst obAndI;
obAndI.interst = interst;
obAndI.observer = ob;
m_listObservers->push_back(obAndI);
}
}
void Subject::Detach(Observer* ob,InterestAspects interst)
{
if (m_listObservers && ob) {
for (ListObserver::iterator it =m_listObservers->begin();
it !=m_listObservers->end(); ++it)
{
if(it->interst == interst && it->observer == ob){
m_listObservers->erase(it);
break;
}
}
//m_listObservers->remove(obAndI);
}//if
}
void Subject::Notify(InterestAspects interst)
{
ObserverAndInterst obAndI;
if(m_listObservers){
for (ListObserver::iterator it =m_listObservers->begin();
it !=m_listObservers->end(); ++it)
{
obAndI = (*it);
if(obAndI.interst & interst)
(obAndI.observer)->Update(this, obAndI.interst);
}
}
}
//
// SipUser.cpp
// PatternObserver
#include "SipUser.h"
#include "PatternObserverType.h"
//采用的是拉模式,由观察者自身去向目标请求名字和状态
voidSipUser::Update(Subject* theChangedSubject,InterestAspects intersts)
{
SipUser* theChangedUser = (SipUser*)theChangedSubject;
string name = theChangedUser->GetName();
int state = theChangedUser->GetState();
std::cout<<m_strName<<" Got a Change:"<<endl;
std::cout<<"name = "<<name<<", state = "<<state<<endl;
}