观察者模式(Observer)
观察者模式是目前应用最广、影响范围最大的模式之一,因为 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; /* 保存观察者的链表对象 */
};
应用场景
- 侦听事件驱动程序设计中的外部事件
- 侦听/监视某个对象的状态变化
- 发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者
适用于: 定义对象间一种一对多的依赖关系,使得每一个对象改变状态,则所有依赖于他们的对象都会得到通知。 使用场景:定义了一种一对多的关系,让多个观察对象(公司员工)同时监听一个主题对象(秘书),主题对象状态发生变化时,会通知所有的观察者,使它们能够更新自己。
应用实例
#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 ;
}