观察者模式是目前应用最广、影响范围最大的模式之一,因为 Observer 的一个实例Model/View/Control( MVC) 结构在系统开发架构设计中有着很重要的地位和意义, MVC实现了业务逻辑和表示层的解耦。个人也认为 Observer 模式是软件开发过程中必须要掌握和使用的模式之一。在 MFC 中, Doc/View(文档视图结构)提供了实现 MVC 的框架结构。同样Qt中核心机制:信号和槽的实现也同样有观察者的影子。
Observer 模式要解决的问题为: 建立一个一( Subject)对多( Observer) 的依赖关系, 并且做到当“一” 变化的时候, 依赖这个“一”的多也能够同步改变。Observer 模式也称为发布-订阅( publish-subscribe),目标就是通知的发布者,观察者则是通知的订阅者(接受通知)。 最常见的一个例子就是: 对同一组数据进行统计分析时候, 我们希望能够提供多种形式的表示(例如以表格进行统计显示、 柱状图统计显示、 百分比统计显示等)。这些表示都依赖于同一组数据, 我们当然需要当数据改变的时候, 所有的统计的显示都能够同时改变。Observer 模式就是解决了这一个问题。Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
观察者(Observer)模式典型的结构图如下:
这里的目标 Subject 提供依赖于它的观察者 Observer 的注册( Attach) 和注销( Detach)操作,并且提供了使得依赖于它的所有观察者同步的操作( Notify)。 观察者 Observer 则提供一个 Update 操作, 注意这里的 Observer 的 Update 操作并不在 Observer 改变了 Subject 目标状态的时候就对自己进行更新, 这个更新操作要延迟到 Subject 对象发出 Notify 通知所有Observer 进行修改(调用 Update)。
Subject(被观察者)
被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject需要维持(添加,删除,通知)一个观察者对象的队列列表。
ConcreteSubject
被观察者的具体实现。包含一些基本的属性状态及其他操作。
Observer(观察者)
接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。
ConcreteObserver
观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。
template <typename T> class IObserver { /* 更新观察者 */ virtual void Update(const T &t) = 0; virtual ~IObserver(){} }; template <typename T> class CSubject { public: CSubject() { } CSubject(const CSubject<T>& oValue) { m_oObserverList = oValue.m_oObserverList; } virtual ~CSubject() { Clear(); } /* 注册观察者 */ qint32 Attach(IObserver<T> *pObserver) { if (NULL == pObserver) { return COMMON_INVALIDPARAM; } typename std::list<IObserver<T> *>iterator it = std::find(m_oObserverList.begin(), m_oObserverList.end(), pObserver); if (it != m_oObserverList.end()) { return COMMON_ALREADY_EXIST; } m_oObserverList.push_back(pObserver); return COMMON_SUCCEED; } /* 注销观察者 */ void Detatch(IObserver<T> *pObserver) { if (NULL == pObserver) { return COMMON_INVALIDPARAM; } typename std::list<IObserver<T> *>iterator it = std::find(m_oObserverList.begin(), m_oObserverList.end(), pObserver); if (m_oObserverList.end() == it) { return COMMON_NOTFOUND; } m_oObserverList.erase(it); return COMMON_SUCCEED; } /* 目标状态发生变化时,通知所有的观察者 */ void Notify(const T &t) { typedef std::list<IObserver<T> *>::iterator it = m_oObserverList.begin(); for (; it != m_oObserverList.end(); ++it) { (*it)->Update(t); } } /* 从清空所有观察者 */ void Clear() { m_oObserverList.clear(); } private: std::list<IObserver<T> *> m_oObserverList; /* 保存观察者的链表对象 */ };
适用于: 定义对象间一种一对多的依赖关系,使得每一个对象改变状态,则所有依赖于他们的对象都会得到通知。 使用场景:定义了一种一对多的关系,让多个观察对象(公司员工)同时监听一个主题对象(秘书),主题对象状态发生变化时,会通知所有的观察者,使它们能够更新自己。
#include <iostream> using namespace std; #include "vector" #include "string" class Secretary; //玩游戏的同事类(观察者) class PlayserObserver { public: PlayserObserver(string name, Secretary *secretary) { m_name = name; m_secretary = secretary; } void update(string action) { cout << "观察者收到action:" << action << endl; } private: string m_name; Secretary *m_secretary; }; //秘书类(主题对象,通知者) class Secretary { public: void addObserver(PlayserObserver *o) { v.push_back(o); } void Notify(string action) { for (vector<PlayserObserver *>::iterator it= v.begin(); it!=v.end(); it++ ) { (*it)->update(action); } } void setAction(string action) { m_action = action; Notify(m_action); } private: string m_action; vector<PlayserObserver *> v; }; void main() { //subject 被观察者 Secretary *s1 = new Secretary; //具体的观察者 被通知对象 PlayserObserver *po1 = new PlayserObserver("小张", s1); //PlayserObserver *po2 = new PlayserObserver("小李", s1); s1->addObserver(po1); //s1->addObserver(po2); s1->setAction("老板来了"); s1->setAction("老板走了"); cout<<"hello..."<<endl; system("pause"); return ; }