意图:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这一模式中的关键对象是目标和观察者。这种交互也称为发布订阅。
适用性:
1当一个抽象模型有两个方面,其中一个方面依赖于另外一个方面。将这二者封装在独立的对象中以使得它们可以各自独立的改变和复用。
2当一个对象的改变需要同时改变其他对象,而不知道具体有多少对象待改变
3当一个对象必须通知其他对象,而它又不能假定其他对象是谁,即不希望这些对象是紧耦合的。
效果:
1目标和观察者之间的抽象耦合
2支持广播通信
3意外的更新
实现:
1创建目标到其观察之者间的映射,最简单的方法是显式的在目标中保存对他们的引用。或者用关联查找机制来维护目标到观察者的映射。
2观察多个目标
3谁触发更新
A由目标对象的状态设定操作在改变目标对象的状态后自动调用notify
B让客户负责在适当的时候调用Notify
4对已删除目标的悬挂引用,当一个目标被删除时,让它通知它的观察者将对该目标的引用复位。
5在发出通知前确保目标的状态自身是一致的
6 显式的指定兴趣的改变。 可以扩展注册的接口,让各观察者注册为仅对特定事件感兴趣,以提高更新效率
7如果目标和观察者之间的依赖关系特别复杂,需要一个ChangeManager
来维护,可以有Mediator中介者来实现。
The sample code is as below:
Observer.h
- #include <list>
- #include <iterator>
- #include <iostream>
- using namespace std;
- class Subject;
- class Observer
- {
- public:
- virtual ~Observer(){cout<<"An observer is destoryed"<<endl;}
- virtual void Update(Subject* theChangedSubject) = 0;
- protected:
- Observer() {cout<<"An observer is created"<<endl;}
- };
- class Subject
- {
- public:
- virtual ~Subject() {cout<<"A subjct is destroyed"<<endl; }
- virtual void Attach(Observer*);
- virtual void Detach(Observer*);
- virtual void Notify();
- protected:
- Subject() {cout<<"A subjct is created"<<endl;}
- private:
- list<Observer*> _observers;
- };
- class ClockTimer:public Subject
- {
- public:
- ClockTimer(){cout<<"A clock timer is created"<<endl;}
- void Tick() {Notify();}
- };
- class DigitalClock: public Observer
- {
- public:
- DigitalClock(ClockTimer* s);
- virtual ~DigitalClock();
- virtual void Update(Subject *);
- virtual void Draw();
- private:
- ClockTimer* _subject;
- };
- class AnalogClock: public Observer
- {
- public:
- AnalogClock(ClockTimer* s);
- virtual ~AnalogClock();
- virtual void Update(Subject *);
- virtual void Draw();
- private:
- ClockTimer* _subject;
- };
Observer.cpp
- #include <list>
- #include <iostream>
- using namespace std;
- #include "Observer.h"
- void Observer::Update(Subject * theChangedSubject)
- {
- cout<<"The Subject is changed"<<endl;
- }
- void Subject::Attach(Observer* o)
- {
- //_observers->push_back(o);
- _observers.push_back(o);
- }
- void Subject::Detach(Observer* o)
- {
- //_observers->remove(o);
- _observers.remove(o);
- }
- void Subject::Notify()
- {
- for(list<Observer*>::iterator ixx= _observers.begin(); ixx != _observers.end();++ixx)
- {
- (*ixx)->Update(this);
- }
- }
- DigitalClock::DigitalClock(ClockTimer* s)
- {
- _subject = s;
- _subject->Attach(this);
- }
- DigitalClock::~DigitalClock()
- {
- _subject->Detach(this);
- }
- void DigitalClock::Update(Subject* theChangedSubject)
- {
- if (theChangedSubject == _subject)
- {
- Draw();
- }
- }
- void DigitalClock::Draw()
- {
- cout<<"Draw the time in Digital Clock"<<endl;
- }
- AnalogClock::AnalogClock(ClockTimer* s)
- {
- _subject = s;
- _subject->Attach(this);
- }
- AnalogClock::~AnalogClock()
- {
- _subject->Detach(this);
- }
- void AnalogClock::Update(Subject* theChangedSubject)
- {
- if (theChangedSubject == _subject)
- {
- Draw();
- }
- }
- void AnalogClock::Draw()
- {
- cout<<"Draw the time in Analog Clock"<<endl;
- }
main.cpp
- #include<iostream>
- #include "Observer.h"
- using namespace std;
- int main()
- {
- ClockTimer* timer = new ClockTimer();
- AnalogClock* analogClock = new AnalogClock(timer);
- DigitalClock* digitalClock = new DigitalClock(timer);
- timer->Notify();
- return 0;
- }