1. 简单描述
观察者模式主要包括:Subject与Observers。通常observer会有多个而subject只有一个。observer将自己注册到subject中,当subject中的信息发生变化时subject便会通知该observer进行更新。subject保存所有注册的observer实例信息,在信息发生变化时通知其保存的每一个observer。这种方式是回调的一种应用。observer保存着subject的指针,subject使用array或其它同期保存observer。
subject通知observer时可以使用“推”或“拉”的方式,“推”就是subject在通知observer信息变化时直接将变化的信息作为参数传递给observer,“拉”就是subject仅仅通知observer信息有变化,而由observer自己去取得变化的信息。在多线程环境下,“推”的方式更能保证数据的准确性。
2.实例程序
subject中保存注册的observer的指针,为了使每个observer只在subject中保存一份(信息发生变化时每个observer只通知一次)使用std::set保存指针信息。
2.1 定义信息提供者
信息提供者(subject)包含observer集合成员,用来储存所有注册的观察者。attach(Observer*)用来将新的observer放入集合中。notify()接口实现当有数据变化时,遍历observer集合并通知所有注册的observer。
注意:例子中将observer的raw指针放入Observer集合,但实际使用中应该使用弱指针来避免内存泄露以及野指针问题。
//subject.h
#include <set>
class Observer;
class Subject
{
public:
Subject(){}
~Subject(){}
// regist a new observer if it does not in m_observer;
void attach(Observer* observer);
// remove one observer in m_observer;
void detach(Observer* observer);
// notify the observers to update messages;
void notify();
private:
std::set<Observer*> m_observer;
typedef std::set<Observer*>::iterator ObserverIter;
};
//subject.cpp
#include <iostream>
#include "Subject.h"
#include "Observer.h"
using namespace std;
void Subject::attach(Observer* observer)
{
if (NULL != observer)
{
pair<ObserverIter, bool> result = m_observer.insert(observer);
if (true == result.second)
{
cout<<"Subject::attach successfully registed"<<endl;
}
else
{
cout<<"Subject::attach already registed"<<endl;
}
}
}
void Subject::detach(Observer* observer)
{
if (NULL != observer)
{
int num = m_observer.erase(observer);
if (0 < num)
{
cout<<"Subject::detach successfully removed"<<endl;
}
else
{
cout<<"Subject::detach do not need remove"<<endl;
}
}
}
void Subject::notify()
{
for (ObserverIter i = m_observer.begin(); i != m_observer.end(); ++i)
{
(*i)->update(8);
}
}
2.2 定义观察者
观察者在构造时接收一个subject的指针,用来将自己注册到相应的subject中去。观察者实现了一个uodate()接口用来处理“观察到的”新数据。// observer.h
class Subject;
class Observer
{
public:
// regist to subject when construct
Observer(Subject* subject): m_subject(subject){}
virtual ~Observer(){}
// update message
virtual void update(int updateStr) = 0;
// remove from the old subject and regist to a new subject;
void regist(Subject* subject);
// remove from the old subject;
void remove();
protected:
Subject* m_subject;
};
class ObserverA: public Observer
{
public:
ObserverA(Subject* subject);
virtual ~ObserverA(){}
virtual void update(int updateStr);
};
class ObserverB: public Observer
{
public:
ObserverB(Subject* subject);
virtual ~ObserverB(){}
virtual void update(int updateStr);
};
// observer.cpp
#include <iostream>
#include "Observer.h"
#include "Subject.h"
using namespace std;
void Observer::regist(Subject* subject)
{
if (NULL == subject)
{
cout<<"Observer::regist subject is NULL"<<endl;
return;
}
if (m_subject != subject)
{
remove();
m_subject = subject;
m_subject->attach(this);
}
else
{
cout<<"Observer::regist no need attach operation"<<endl;
}
}
void Observer::remove()
{
if (NULL != m_subject)
{
m_subject->detach(this);
m_subject = NULL;
}
}
ObserverA::ObserverA(Subject* subject): Observer(subject)
{
if (NULL != m_subject)
{
m_subject->attach(this);
}
}
void ObserverA::update(int updateStr)
{
cout<<"ObserverA::update: "<<updateStr<<endl;
}
ObserverB::ObserverB(Subject* subject): Observer(subject)
{
if (NULL != m_subject)
{
m_subject->attach(this);
}
}
void ObserverB::update(int updateStr)
{
cout<<"ObserverB::update: "<<updateStr<<endl;
}
2.3 测试程序
// test.cpp
#include <iostream>
#include "Subject.h"
#include "Observer.h"
using namespace std;
int main(int argc, char const *argv[])
{
/* code */
Subject* pSubject = new Subject();
ObserverA obA(pSubject);
ObserverB obB(pSubject);
pSubject->notify();
obB.remove();
pSubject->notify();
obB.regist(pSubject);
obB.regist(pSubject);
pSubject->notify();
return 0;
}