一、描述
观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其它的对象做出相应的改变。做到这一点的设计方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行动的协调一致,保证高度的协作(Collaboration)。
Observer 模式典型的结构图为:
图 2-1:Observer Pattern 结构图
这里的目标 Subject 提供依赖于它的观察者 Observer 的注册(Attach)和注销(Detach)操作,并且提供了使得依赖于它的所有观察者同步的操作(Notify)。观察者 Observer 则提供一个 Update 操作,注意这里的 Observer 的 Update 操作并不在 Observer 改变了 Subject 目标状态的时候就对自己进行更新,这个更新操作要延迟到 Subject 对象发出 Notify 通知所有Observer 进行修改(调用 Update)。
二、实例:
描述:
《孙子兵法》有云:“知彼知己,百战不殆;不知彼而知己,一胜一负;不知彼,不知己,每战必殆”,那怎么才能知己知彼呢?知己是很容易的,自己的军队嘛,很容易知道,那怎么知彼呢?安插间谍是很好的一个办法,我们今天就来讲一个间谍的故事。
韩非子大家都应该记得吧,法家的代表人物,主张建立法制社会,实施重罚制度,真是非常有远见呀,看看现在社会在呼吁什么,建立法制化的社会,在 2000 多年前就已经提出了。大家可能还不知道,法家还有一个非常重要的代表人物,李斯,对,就是李斯,秦国的丞相,最终被残忍的车裂的那位,李斯和韩非子都是荀子的学生,李斯是师兄,韩非子是师弟,若干年后,李斯成为最强诸侯秦国的上尉,致力于统一全国,于是安插了间谍到各个国家的重要人物的身边,以获取必要的信息,韩非子作为韩国的重量级人物,身边自然没少间谍了,韩非子早饭吃的什么,中午放了几个 P,晚上在做什么娱乐,李斯都了如指掌,那可是相隔千里!怎么做到的呢?间谍呀! 好,我们先通过程序把这个过程展现一下,看看李斯是怎么监控韩非子,先看类图:
我的工程目录:
注释:
main(),主程序
IObservable,被观察者接口
CHanFeiZiObservable,被观察者韩非子
IObserver,观察者接口
CLiSiObserver,观察者李斯
CZhouSiObserver观察者周斯
说明:将观察者聚集到被观察者韩非子身边,韩非子的每一个举动都会通知给观察者,如李斯或周斯。
注意:最多允许一个对象既是观察者也是被观察者。就像数据库中的触发器一样,成为一个复杂的链就很难维护了。观察者类似于委托的处理方式。
观察者接口:IObserver
IObserver.h
- #ifndef __Observer__IObserver__
- #define __Observer__IObserver__
-
- #include <iostream>
- #include <string>
- using std::string;
- class IObserver
- {
- public:
- IObserver(string _name){this->m_name = _name;}
- virtual ~IObserver(void){}
-
-
- virtual void Update(string context) = 0;
-
-
- virtual string GetName() = 0;
-
- protected:
- string m_name;
- };
-
-
- #endif /* defined(__Observer__IObserver__) */
观察者李斯:LiSiObserver类
LiSiObserver.h
- #ifndef __Observer__LiSiObserver__
- #define __Observer__LiSiObserver__
-
- #include <iostream>
- #include "IObserver.h"
-
- class CLiSiObserver:public IObserver
- {
- public:
- CLiSiObserver(void);
- ~CLiSiObserver(void);
-
- void Update(string context);
- string GetName();
- private:
- void ReportToQinShiHuang(string report);
- };
-
-
- #endif /* defined(__Observer__LiSiObserver__) */
LiSiObserver.cpp
- #include "LiSiObserver.h"
- using std::cout;
- using std::endl;
- using std::string;
-
- CLiSiObserver::CLiSiObserver(void):IObserver("李斯")
- {
- }
-
- CLiSiObserver::~CLiSiObserver(void)
- {
-
- }
-
-
- void CLiSiObserver::Update(string context)
- {
- cout << "李斯:观察到韩非子活动,开始向老板汇报了..." << endl;
- this->ReportToQinShiHuang(context);
- cout << "李斯:汇报完毕,秦老板赏给他两个萝卜吃吃..." << endl;
- }
-
-
- void CLiSiObserver::ReportToQinShiHuang(string report)
- {
- cout << "李斯:报告,秦老板!韩非子有活动了--->" << report.c_str() << endl;
- }
-
- string CLiSiObserver::GetName()
- {
- return m_name;
- }
观察者周斯:ZhouSiObserver类
ZhouSiObserver.h
- #ifndef __Observer__ZhouSiObserver__
- #define __Observer__ZhouSiObserver__
-
- #include <iostream>
- #include "IObserver.h"
- using std::string;
- class CZhouSiObserver:public IObserver
- {
- public:
- CZhouSiObserver(void);
- ~CZhouSiObserver(void);
- void Update(string context);
- string GetName();
- private:
- void Cry(string report);
- };
-
- #endif /* defined(__Observer__ZhouSiObserver__) */
ZhouSiObserver.cpp
- #include "ZhouSiObserver.h"
- using std::cout;
- using std::endl;
- using std::string;
-
- CZhouSiObserver::CZhouSiObserver(void):IObserver("周斯")
- {
-
- }
-
- CZhouSiObserver::~CZhouSiObserver(void)
- {
-
- }
-
-
- void CZhouSiObserver::Update(string context)
- {
- cout << "周斯:观察到韩非子活动,自己也开始活动了..." << endl;
- this->Cry(context);
- cout << "周斯:真真的哭死了..." << endl;
- }
-
-
- void CZhouSiObserver::Cry(string report)
- {
- cout << "周斯:因为" << report.c_str() << ", ————所以我悲伤呀!" << endl;
- }
-
- string CZhouSiObserver::GetName()
- {
- return m_name;
- }
被观察者接口:IObservable
IObservable.h
- #ifndef __Observer__IObservable__
- #define __Observer__IObservable__
-
- #include <iostream>
- #include "IObserver.h"
- using std::string;
-
- class IObservable
- {
- public:
- IObservable(void){}
- virtual ~IObservable(void){}
-
- virtual void AddObserver(IObserver *pObserver) = 0;
-
-
- virtual void DeleteObserver(IObserver *pObserver) = 0;
-
-
- virtual void NotifyObservers(string context) = 0;
-
- };
-
- #endif /* defined(__Observer__IObservable__) */
被观察者韩非子:HanFeiziObservable类
HanFeiziObservable.h
- #ifndef __Observer__HanFeiziObservable__
- #define __Observer__HanFeiziObservable__
-
- #include <iostream>
- #include "IObserver.h"
- #include "IObservable.h"
- #include <vector>
- using std::vector;
-
- class CHanFeiziObservable:public IObservable
- {
- public:
- CHanFeiziObservable(void);
- ~CHanFeiziObservable(void);
- void AddObserver(IObserver *pObserver);
- void DeleteObserver(IObserver *pObserver);
- void NotifyObservers(string context);
-
- void HaveBreakfast();
-
- void HaveFun();
- private:
- vector<IObserver*> m_observerList;
- typedef vector<IObserver*>::const_iterator ObserverList_C_iterator;
- };
-
-
-
- #endif /* defined(__Observer__HanFeiziObservable__) */
HanFeiziObservable.cpp
- #include "HanFeiziObservable.h"
- using std::string;
- using std::cout;
- using std::endl;
-
- CHanFeiziObservable::CHanFeiziObservable(void)
- {
-
- }
-
- CHanFeiziObservable::~CHanFeiziObservable(void)
- {
-
- }
-
- void CHanFeiziObservable::AddObserver(IObserver *pObserver)
- {
- m_observerList.push_back(pObserver);
- }
-
- void CHanFeiziObservable::DeleteObserver(IObserver *pObserver)
- {
- ObserverList_C_iterator it = m_observerList.begin();
- for (; it != m_observerList.end(); it++)
- {
- string name = (*it)->GetName();
- if (name.compare(pObserver->GetName())==0)
- {
-
- }
- }
- }
-
- void CHanFeiziObservable::NotifyObservers(string context)
- {
- ObserverList_C_iterator it = m_observerList.begin();
- for(;it != m_observerList.end();it++)
- {
- (*it)->Update(context);
- }
- }
-
- void CHanFeiziObservable::HaveBreakfast()
- {
- cout << "韩非子:开始吃饭了..." << endl;
- this->NotifyObservers("韩非子在吃饭");
- }
-
-
- void CHanFeiziObservable::HaveFun()
- {
- cout << "韩非子:开始娱乐了..." << endl;
-
- this->NotifyObservers("韩非子在娱乐");
- }
主程序:mainmain.cpp
- #include <iostream>
- #include "IObserver.h"
- #include "LiSiObserver.h"
- #include "ZhouSiObserver.h"
- #include "IObserver.h"
- #include "HanFeiziObservable.h"
- using std::cout;
- using std::endl;
-
- void DoIt()
- {
-
- }
-
- void DoNew()
- {
-
-
-
-
-
-
-
-
- }
-
- void DoNewNew()
- {
-
- cout << "----------用更新的方法再试试----------" << endl;
-
- IObserver *pLiSi = new CLiSiObserver();
- IObserver *pZhouSi = new CZhouSiObserver();
-
-
- CHanFeiziObservable *pHanFeiZi = new CHanFeiziObservable();
-
-
- pHanFeiZi->AddObserver(pLiSi);
- pHanFeiZi->AddObserver(pZhouSi);
-
-
- pHanFeiZi->HaveBreakfast();
-
- delete pLiSi;
- pLiSi = NULL;
- delete pHanFeiZi;
- pHanFeiZi = NULL;
-
- }
-
-
- int main(int argc, const char * argv[])
- {
-
-
- DoNew();
-
-
- DoNewNew();
-
-
- std::cout << "Hello, World!\n";
- return 0;
- }
结果如下:
参考文献:《设计模式之禅》,《GoF_23种设计模式解析》
参考博客: http://www.cnblogs.com/wanggary/archive/2011/04/20/2022975.html