定义对象间的一种一对多的依赖关系 ,让多个观察者对象同时监听某一个主题对象,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新,又叫发布-订阅(publish-subscribe)模式。
在以下任一情况下可以使用观察者模式:
(1)当一个抽象模型有两个方面 ,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
(2)当对一个对象的改变需要同时改变其它对象 , 而不知道具体有多少对象有待改变。
(3)当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之 , 你不希望这些对象是紧密耦合的。
Observer:抽象观察者,是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
Subject (抽象主题,抽象通知者) :该角色是一个抽象类或接口,它把所有对观察者的引用保存在一个聚集里,每个通知者都可以有任何数量的观察者,定义了增加、删除、通知观察者对象的方法。
ConcreteSubject(具体主题,具体通知者):将有关状态存入各ConcrereObserver对象,当它的状态发生改变时 , 向它的各个观察者发出通知。

(1)在教室里老师还没有来,同学都在干着各的事情,小张正在打游戏,小李正在抄作业, 现在同学们要求班长当卧底,监视老师,当老师来了通知大家一声。然后打游戏的马上停止,抄作业的也停止。
这里班长相当于是一个通知者, 小张、小李,以及其他同学显然是观察者,他们监听了班长那的消息,一旦老师来了马上采取相关的行动。
(2)对同一组数据进行统计分析时候, 我们希望能够提供多种形式的表示 (例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据, 我们当然需要当数据改变的时候, 所有的统计的显示都能够同时改变。
- #include"iostream"
- #include"list"
- #include"string"
-
- using namespace std;
-
- class Subject;
-
- /*抽象观察者,为所有具体观察者定义一个接口,在得到主题的通知时更新自己
- 如,干着各种事情的同学*/
- class AbsObserver
- {
- public:
- AbsObserver(string name, Subject* sub)
- {
- this->name = name;
- this->subject = sub;
- }
-
- virtual void update(int value) = 0;
-
- protected:
- string name;
- Subject* subject;
- };
-
- /*具体观察者*/
- class PlayGameStu :public AbsObserver
- {
- public:
- PlayGameStu(string name, Subject* sub) :AbsObserver(name, sub) {}
-
- void update(int value)
- {
- stopPlayGame(value);
- }
-
- void stopPlayGame(int value)
- {
- cout << name << "stopPlayGame" << endl;
- }
-
- };
-
- class CopyWorkStu :public AbsObserver
- {
- public:
- CopyWorkStu(string name, Subject* sub) :AbsObserver(name, sub) {}
-
- void update(int value)
- {
- stopCopyWork(value);
- }
- void stopCopyWork(int value)
- {
- cout << name << "stopCopyWork" << endl;
- }
- };
-
- //抽象主题,通知者、班长
- class Subject
- {
- public:
- virtual void addObserver(AbsObserver *observer) = 0;
- virtual void removeObserver(AbsObserver *observer) = 0;
- virtual void notify() = 0;
-
- void setState(int value)
- {
- stateTeacher = value;
- printf("当前状态:%d\n", value);
- notify();
- }
-
- protected:
- list
observers; - int stateTeacher; //老师状态
- };
-
- /*(具体主题,通知者、班长):该角色继承或实现了抽象主题,定义了一个集合存入注册过的具体观察者对象,
- 在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知*/
- class ConcreteSubject :public Subject
- {
- public:
- void addObserver(AbsObserver *observer)
- {
- observers.push_back(observer);
- }
-
- void removeObserver(AbsObserver *observer)
- {
- list
::iterator it; - for (it = observers.begin(); it != observers.end(); it++)
- {
- if (*it == observer)
- {
- observers.remove(observer);
- break;
- }
- }
- }
-
- void notify()
- {
- list
::iterator it; -
- for (it = observers.begin(); it != observers.end(); it++)
- {
- (*it)->update(stateTeacher);
- }
- }
-
- };
-
-
- int main()
- {
- //
- Subject* subject = new ConcreteSubject;
-
- AbsObserver* stuPG = new PlayGameStu("xiaoming", subject);
- AbsObserver* stuCW = new CopyWorkStu("xiaoli", subject);
-
- //
- subject->addObserver(stuPG);
- subject->addObserver(stuCW);
-
- subject->setState(1);
-
- subject->setState(2);
-
- return 0;
- }
-