设计模式--观察者模式
2013-09-28 14:10
316 查看
在查一个问题时,遇到了观察者模式的概念。印象中,在之前的项目中,好像遇到过这种设计模式,只是当时,自己不知道那就是观察者模式,这里要膜拜一下,这个模式的发明者,太有才了。
下面是观察者模式的简单介绍:
观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,他可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现——这一点为程序提供了更大的灵活性。
示例代码(代码是C++的):
下面是观察者模式的简单介绍:
1基本简介
观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。2实现方式
观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。在刚才的例子中,业务数据是被观察对象,用户界面是观察者。观察者和被观察者之间存在“观察”的逻辑关联,当被观察者发生改变的时候,观察者就会观察到这样的变化,并且做出相应的响应。如果在用户界面、业务数据之间使用这样的观察过程,可以确保界面和数据之间划清界限,假定应用程序的需求发生变化,需要修改界面的表现,只需要重新构建一个用户界面,业务数据不需要发生变化。3“观察”
实现观察者模式的时候要注意,观察者和被观察对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察对象之间紧密的耦合起来,从根本上违反面向对象的设计的原则。无论是观察者“观察”观察对象,还是被观察者将自己的改变“通知”观察者,都不应该直接调用。4过程
实现观察者模式有很多形式,比较直观的一种是使用一种“注册——通知——撤销注册”的形式。下面的三个图详细的描述了这样一种过程:观察者
(Observer)将自己注册到被观察对象(Subject)中,被观察对象将观察者存放在一个容器(Container)里。被观察
被观察对象发生了某种变化(如图中的SomeChange),从容器中得到所有注册过的观察者,将变化通知观察者。撤销观察
观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。观察者将自己注册到被观察者的容器中时,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,他可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现——这一点为程序提供了更大的灵活性。
示例代码(代码是C++的):
#include <iostream> #include <set> #include <string> using namespace std; /////////////////////抽象模式定义 class CObservable; //观察者,纯虚基类 class CObserver { public: CObserver::CObserver(){}; virtual CObserver::~CObserver(){}; //当被观察的目标发生变化时,通知调用该方法 //来自被观察者pObs, 扩展参数为pArg virtual void Update(CObservable* pObs, void* pArg = NULL) = 0; }; //被观察者,即Subject class CObservable { public: CObservable() : m_bChanged(false) {}; virtual ~CObservable() {}; //注册观察者 void Attach(CObserver* pObs); //注销观察者 void Detach(CObserver* pObs); //注销所有观察者 void DetachAll(); //若状态变化,则遍历观察者,逐个通知更新 void Notify(void* pArg = NULL); //测试目标状态是否变化 bool HasChanged(); //获取观察者数量 int GetObserversCount(); protected: //设置状态变化!!!必须继承CObservable才能设置目标状态 void SetChanged(); //初始化目标为未变化状态 void ClearChanged(); private: bool m_bChanged; //状态 set<CObserver*> m_setObs; //set保证目标唯一性 }; /////////////////////抽象模式实现 void CObservable::Attach(CObserver* pObs) { if (!pObs) return; m_setObs.insert(pObs); } void CObservable::Detach(CObserver* pObs) { if (!pObs) return; m_setObs.erase(pObs); } void CObservable::DetachAll() { m_setObs.clear(); } void CObservable::SetChanged() { m_bChanged = true; } void CObservable::ClearChanged() { m_bChanged = false; } bool CObservable::HasChanged() { return m_bChanged; } int CObservable::GetObserversCount() { return m_setObs.size(); } void CObservable::Notify(void* pArg /* = NULL */) { if (!HasChanged()) return; cout << "notify observers…" << endl; ClearChanged(); set<CObserver*>::iterator itr = m_setObs.begin(); for (; itr != m_setObs.end(); itr++) { (*itr)->Update(this, pArg); } } /////////////////////具体应用类定义和实现 //bloger是发布者,即被观察者(subject) class CBloger : public CObservable { public: void Publish(const string &strContent) { cout << "bloger publish, content: " << strContent << endl; SetChanged(); Notify(const_cast<char*>(strContent.c_str())); } }; //portal是发布者,即被观察者(subject) class CPortal : public CObservable { public: void Publish(const string &strContent) { cout << "portal publish, content: " << strContent << endl; SetChanged(); Notify(const_cast<char*>(strContent.c_str())); } }; //RSS阅读器,观察者 class CRSSReader : public CObserver { public: CRSSReader(const string &strName) : m_strName(strName){} virtual void Update(CObservable* pObs, void* pArg = NULL) { char* pContent = static_cast<char*>(pArg); //观察多个目标 if (dynamic_cast<CBloger*>(pObs)) { cout << m_strName << " updated from bloger, content: " << pContent << endl; } else if (dynamic_cast<CPortal*>(pObs)) { cout << m_strName << " updated from portal, content: " << pContent << endl; } } private: string m_strName; }; //Mail阅读器,观察者 class CMailReader : public CObserver { public: CMailReader(const string &strName) : m_strName(strName){} virtual void Update(CObservable* pObs, void* pArg = NULL) { char* pContent = static_cast<char*>(pArg); if (dynamic_cast<CBloger*>(pObs)) { cout << m_strName << " updated from bloger, content: " << pContent << endl; } if (dynamic_cast<CPortal*>(pObs)) { cout << m_strName << " updated from portal, content: " << pContent << endl; } } private: string m_strName; }; /////////////////Main int main() { //目标(被观察者) CBloger* pBloger = new CBloger(); CPortal* pPortal = new CPortal(); //观察者. 一个观察者可以观察多个目标 CRSSReader* pRssReader = new CRSSReader("rss reader"); CMailReader* pMailReader = new CMailReader("mail reader"); pBloger->Attach(pRssReader); //bloger注册观察者 pBloger->Attach(pMailReader); //bloger注册观察者 pPortal->Attach(pRssReader); //portal注册观察者 pPortal->Attach(pMailReader); //portal注册观察者 //博客发布信息 pBloger->Publish("博客分享设计模式"); cout << endl; //门户发布信息 pPortal->Publish("门户分享设计模式"); cout << "\nportal detached mail reader" << endl; pPortal->Detach(pMailReader); cout << "portal observers count: " << pPortal->GetObserversCount() << endl << endl; pPortal->Publish("门户分享设计模式"); system("pause"); return 0; }
相关文章推荐
- 设计模式-观察者模式(上)
- java_设计模式_观察者模式_Observer Pattern(2016-07-27)
- Java 设计模式_观察者模式
- Java设计模式-观察者模式(Observer)
- 设计模式之观察者模式
- IOS设计模式第七篇之观察者设计模式
- 设计模式——观察者模式 Observer
- c# 设计模式:观察者模式
- iOS中常见的设计模式(MVC/单例/委托/观察者)
- 设计模式(二)观察者模式
- 【设计模式】观察者模式
- java设计模式-观察者(发布-订阅)模式
- 【设计模式】工场模式 || 抽象工厂 || 观察者模式 || 代理模式
- java设计模式-----观察者
- Java设计模式—观察者模式
- 二十三种设计模式之观察者模式简述
- 设计模式学习之——观察者模式
- 设计模式-2-观察者模式
- 观察者设计模式-猫和老鼠
- 设计模式之观察者模式