标签:
1.观察者模式 Observer
首先根据字面意思肯定知道有 观察者 和 被观察者。 根据模式规定,这是一个一对多的依赖关系。
当被观察者更新状态,并且发出通知 观察者,观察者做出相对应的动作。这个前提是观察者关注了他所需要的内容。
比如:
a. 移动公司调整套餐资费,发出短信告诉你最新资费,你使用手机查看新的内容(或许你就要变更资费了)。此时移动公司是被观察者,你是观察者。
b. 你关注了人民日报公众号,人民日报在公众号发布,明天收复菲律宾,让他回到祖国的怀抱,你拿起手机根据内容,定了一张明天飞往南沙群岛的几篇,准备看风景。
总的来说
2. 一个错误例子的分析
背景:被观察者:papi酱 ; 观察者:小A, 小B, 小C
主题:直播
7月17日,papi酱 更新状态 下午 4点 直播,小A,小B,小C同时关注Papi酱,都收到了消息,表示会看直播。
伪代码:
class Papi酱; public : void 直播InfoChanged() { QString strInfo = get直播Info(); 小A.update( strInfo ); //收到通知,去看直播 小B.update( strInfo ); //收到通知,去看直播 小C.update( strInfo ); //收到通知,去看直播 // 果断不喜欢了,这里还得再Papi酱的代码手动去掉 }如果这么写的话,我们可以达到目的,但是过了段时间小C不再喜欢看Papi酱的直播了,还得Papi酱手动修改自己维护列表(代码),把小C去掉,传说中Papi酱有2000万粉丝啊,那不把她累死了。
这个例子就是类之间的调用,直接紧密的耦合起来了。 从根本上违反了面向对象的设计原则。
那么我们怎么做才好呢?
比较直观的一种是使用一种“注册——通知——撤销注册”的形式
(上图假设 小A、小B、小C只关注了Papi酱,没人关注习大大,当然你可以让小A、小B同时也关注老习)
3. 下来看看代码:
观察者接口 : QObserver
被观察者接口:QObservable
QObserver.h
#ifndef QOBSERVER #define QOBSERVER <span style="color:#5555ff;">#include</span><span style="color:#c0c0c0;"> </span><span style="color:#ff55ff;"><QObject> // .h不认识NULL所以加了 这个头文件</span> class QObservable; class QObserver { public: virtual ~QObserver() { } //当被观察的目标发生变化时,通知调用该方法 //来自被观察者pObs,扩展参数为pArg virtual void Update(QObservable *pObs, void *pArg = NULL) = 0; }; #endif // QOBSERVER
QObservable.h
#ifndef QOBSERVABLE_H #define QOBSERVABLE_H #include "QObserver.h" #include <QSet> class QObservable { public: QObservable(); virtual ~QObservable(){} // 注册观察者 void Attach(QObserver *pObs); // 注销观察者 void Detach(QObserver *pObs); // 注销所有观察者 void DetachAll(); // 若状态变化,则遍历所有观察者,逐个通知更新 void Notify(void *pArg = NULL); // 测试目标状态是否变化 bool HasChanged(); // 获取观察者数量 int GetObserversCount(); protected: // 设置状态变化!!!必须继承QObervable才能设置目标状态 void SetChanged(); // 初始化目标为未变化状态 void ClearChanged(); private: // 状态 bool m_bChanged; // set保证目标唯一性 QSet <QObserver*> m_setObs; }; #endif // QOBSERVABLE_H
QObservable.cpp
#include "QObservable.h" #include <QDebug> QObservable::QObservable():m_bChanged(false) { } void QObservable::Attach(QObserver *pObs) { if(!pObs) return; m_setObs.insert(pObs); } void QObservable::Detach(QObserver *pObs) { if(!pObs) return; m_setObs.remove(pObs); } void QObservable::DetachAll() { m_setObs.clear(); } void QObservable::Notify(void *pArg) { if(!HasChanged()) return; qDebug() << "notify observers…" ; ClearChanged(); QSet<QObserver*>::iterator itr = m_setObs.begin(); for(; itr != m_setObs.end(); itr++) { (*itr)->Update(this,pArg); } } bool QObservable::HasChanged() { return m_bChanged; } int QObservable::GetObserversCount() { return m_setObs.size(); } void QObservable::SetChanged() { m_bChanged=true; } void QObservable::ClearChanged() { m_bChanged=false; }
观察者主要是获取信息(获取信息前提是已经是注册会员了);
被观察者 自身信息变化了才更新,同时用户在我这里注册了才给对应用户更新。
好了
Papi酱和习大大都是被观察的人啊。(这边简单起来就只写Papi酱了,多(观察者)对多(被观察者)和 一对多是一个道理)
QPapi.h
#ifndef QPAPI_H #define QPAPI_H #include "QObservable.h" // 头文件还是得添加下 class QPapi : public QObservable { public: QPapi(); void Zhibo(const QString &strContent); }; #endif // QPAPI_H
#include "QPapi.h" <span style="color:#5555ff;">#include</span><span style="color:#c0c0c0;"> </span><span style="color:#ff55ff;"><QDebug></span> QPapi::QPapi() { } void QPapi::Zhibo(const QString &strContent) { qDebug() << "Papi says:" << strContent; SetChanged(); Notify(const_cast<char*>(strContent.toStdString().c_str())); }
(观察者)小A,小B要上场了。记得要继承接口QObserver
小A.h
#ifndef SMALLA_H #define SMALLA_H #include "QObserver.h" #include "QObservable.h" #include "QPapi.h" #include <QString> class SmallA : public QObserver { public: SmallA(const QString &strName); virtual void Update(QObservable *pObs, void *pArg); private: QString m_strName; }; #endif // SMALLA_H
#include "SmallA.h" #include <QDebug> SmallA::SmallA(const QString &strName) :m_strName(strName) { } void SmallA::Update(QObservable *pObs, void *pArg) { char *pContent = static_cast<char*>(pArg); // 观察目标 if(dynamic_cast <QPapi*>(pObs)) { qDebug() << m_strName << "I know Papi:" << pContent; } else { } }
好了,所有成员到齐了。
下来我们准备运行我们的模式吧。
main.cpp
#include <QCoreApplication> #include <QDebug> #include "SmallA.h" #include "SmallB.h" #include "QPapi.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 目标(被观察者) QPapi * pPapi = new QPapi(); // 观察者 小A 小B SmallA * smallA = new SmallA("Small A"); SmallB * smallB = new SmallB("Small B"); // 小A 小B 都仰慕 Papi酱 并且注册成员粉丝 pPapi->Attach(smallA); pPapi->Attach(smallB); // Papi酱de粉丝 qDebug() <<"fensi:"<< pPapi->GetObserversCount(); // Papi酱说我要直播啦 pPapi->Zhibo("4am zhibo"); // 过了一段日子 小A对Papi酱没兴趣了,取消关注 pPapi->Detach((smallA)); // 看下Papi酱还有多少粉丝 qDebug() <<"fensi:"<< pPapi->GetObserversCount(); // Papi酱又要直播啦 pPapi->Zhibo("8am zhibo"); return a.exec(); }
大概介绍完了,看下 Head Firse设计模式 and
百度百科 就会明白,我是两个都看了遍才明白的。
自己又顺着思路写了下,希望能帮助你。
标签:
原文地址:http://blog.csdn.net/c3060911030/article/details/51928761