以前学习MFC的时候,在MDI框架下,经常会用到CDocument::UpdateAllViews(),然后在CView::Update()里面添加相应的代码。这样做的结果是当其中一个view的内容变化了,那么可以使其他view也作出相应的调整。知道现在才意识到原来这就是Observer模式。
Observer模式的核心其实就是定义一个一对多(one to many)的映射关系,这些对象之间可以相互照应,当一个的内容发生变化时,其他的对象可以作出相应的调整,当然,也可以不调整,要是你愿意。
Observer模式的结构如下:
图中,Subject提供对Observer注册、注销和通知的方法,当需要通知时,Subject::Notify()对所有已注册的Observer进行通知,然后Observer::Update()方法中,你就可以做你需要的事情了。
大概代码如下:
class Observer; class Subject class ConcreteSubject : public Subject public: public: private: private: class Observer class ConcreteObserverA : public Observer public: private: class ConcreteObserverB : public Observer public: private: // ConcreteSubject::~ConcreteSubject() delete m_pList; void ConcreteSubject::DestroyList() void ConcreteSubject::Add(Observer* pObserver) void ConcreteSubject::Remove(Observer* pObserver) void ConcreteSubject::Notify(Observer* pObserver /* = NULL */) for(; iter != m_pList->end(); iter++){ void ConcreteSubject::SetData(int iCnt, int iTotal) Notify(); int ConcreteSubject::GetCount() int ConcreteSubject::GetTotal() // ConcreteObserverA::~ConcreteObserverA() void ConcreteObserverA::Update(Subject* pSubject, Observer* pObserver) ConcreteSubject* pSub = (ConcreteSubject*)pSubject; cout << "ConcreteObserverA::Update() has been called" << endl; // ConcreteObserverB::~ConcreteObserverB() void ConcreteObserverB::Update(Subject* pSubject, Observer* pObserver) ConcreteSubject* pSub = (ConcreteSubject*)pSubject; cout << "ConcreteObserverB::Update() has been called" << endl; |
测试代码
void main() { ConcreteSubject subject; ConcreteObserverA a(&subject); ConcreteObserverB b(&subject); subject.SetData(10, 100); |
输出结果:
ConcreteObserverA::Update() has been called the current count is 10, the total count is 100 ConcreteObserverB::Update() has been called (count, total) : (10, 100), It is 10% ConcreteObserverA::Update() has been called the current count is 20, the total count is 100 ConcreteObserverB::Update() has been called (count, total) : (20, 100), It is 20% |
Observer模式应用很广泛,MFC框架、MVC框架等等都采用了Observer模式。举个例子:我们做了一个天气预报系统,当数据库中的数据发生变化时,我们就可以遍历列表来通知所有的观察者,但是我们并不需要关心观察者是通过电视还是收音机还是广播来接受消息的,我们只要确保它能够接受到数据更新消息就行。如果观察者不需要我们的更新消息了,我们只需要从列表中把它Remove掉就ok,也就是说,观察者他已经把它那可爱的收音机关掉了,呵呵。
Observer模式定义的是一个一对多的对象间关系,他是对象间松耦合,每个对象并不需要知道其他对象的细节,而只需要保证他们能够得到数据更新的消息,仅此而已。