码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式之观察者模式

时间:2017-06-08 23:35:25      阅读:302      评论:0      收藏:0      [点我收藏+]

标签:场景   消息   分离   .com   rtu   else   color   not   virt   

  观察者模式又称发布-订阅模式,是一种行为型模式。在此种模式中,一个目标物件管理所有相依于它的观察者物件,

  并且在它本身的状态改变时主动发出通知。这种模式通常用来实现事件处理系统。

  观察者模式完美的将观察者和被观察的对象分离开,在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。

  观察者模式定义了对象间的一种一对多的依赖关系,以便一个对象状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。

实现方式: 

  观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。实现的时候要注意,

    观察者和被观察对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察对象之间紧密的耦合起来,

    从根本上违反面向对象的设计的原则。无论是观察者“观察”被观察对象,还是被观察对象将自己的改变“通知”观察者,都不应该直接调用。

  比较直观的一种是“注册-通知-撤销注册"的形式。

  技术分享

观察者(Observer)将自己注册到被观察对象(Subject),被观察对象将观察者存放在一个容器里,被观察对象发生了某种变化,

  从容器中得到所有注册过的观察者,将变化通知观察者。观察者告诉被观察者要撤销观察,被观察者从容器中将观察者去除。

  观察者将自己注册到被观察者的容器中,被观察者不应该过问观察者的具体类型,而是应该使用观察者的接口。这样的优点是:

  假定程序中还有别的观察者,那么只要这个观察者也是相同的接口实现即可。一个被观察者可以对应多个观察者,当被观察者发生变化的时候,

  它可以将消息一一通知给所有的观察者。基于接口,而不是具体的实现

观察者模式的适用场景就是一个类发生变化,需要将消息传递到相关很多类的时候。

 

  1 #include<iostream>
  2 #include<set>
  3 #include<string>
  4 using namespace std;
  5 /////////////////////抽象模式定义
  6 class CObservable;
  7 //观察者,纯虚基类
  8 class CObserver
  9 {
 10 public:
 11 CObserver::CObserver(){};
 12 virtual CObserver::~CObserver(){};
 13 //当被观察的目标发生变化时,通知调用该方法
 14 //来自被观察者pObs,扩展参数为pArg
 15 virtual void Update(CObservable*pObs,void*pArg=NULL)=0;
 16 };
 17 //被观察者,即Subject
 18 class CObservable
 19 {
 20 public:
 21 CObservable():m_bChanged(false){};
 22 virtual~CObservable(){};
 23 //注册观察者
 24 void Attach(CObserver*pObs);
 25 //注销观察者
 26 void Detach(CObserver*pObs);
 27 //注销所有观察者
 28 void DetachAll();
 29 //若状态变化,则遍历观察者,逐个通知更新
 30 void Notify(void*pArg=NULL);
 31 //测试目标状态是否变化
 32 bool HasChanged();
 33 //获取观察者数量
 34 int GetObserversCount();
 35 protected:
 36 //设置状态变化!!!必须继承CObservable才能设置目标状态
 37 void SetChanged();
 38 //初始化目标为未变化状态
 39 void ClearChanged();
 40 private:
 41 boolm_bChanged;//状态
 42 set<CObserver*>m_setObs;//set保证目标唯一性
 43 };
 44 /////////////////////抽象模式实现
 45 void CObservable::Attach(CObserver*pObs)
 46 {
 47 if(!pObs)return;
 48 m_setObs.insert(pObs);
 49 }
 50 void CObservable::Detach(CObserver*pObs)
 51 {
 52 if(!pObs)return;
 53 m_setObs.erase(pObs);
 54 }
 55 void CObservable::DetachAll()
 56 {
 57 m_setObs.clear();
 58 }
 59 void CObservable::SetChanged()
 60 {
 61 m_bChanged=true;
 62 }
 63 void CObservable::ClearChanged()
 64 {
 65 m_bChanged=false;
 66 }
 67 bool CObservable::HasChanged()
 68 {
 69 returnm_bChanged;
 70 }
 71 int CObservable::GetObserversCount()
 72 {
 73 returnm_setObs.size();
 74 }
 75 void CObservable::Notify(void*pArg/*=NULL*/)
 76 {
 77 if(!HasChanged())return;
 78 cout<<"notifyobservers…"<<endl;
 79 ClearChanged();
 80 set<CObserver*>::iteratoritr=m_setObs.begin();
 81 for(;itr!=m_setObs.end();itr++)
 82 {
 83 (*itr)->Update(this,pArg);
 84 }
 85 }
 86 /////////////////////具体应用类定义和实现
 87 //bloger是发布者,即被观察者(subject)
 88 class CBloger:public CObservable
 89 {
 90 public:
 91 void Publish(conststring&strContent)
 92 {
 93 cout<<"blogerpublish,content:"<<strContent<<endl;
 94 SetChanged();
 95 Notify(const_cast<char*>(strContent.c_str()));
 96 }
 97 };
 98 //portal是发布者,即被观察者(subject)
 99 class CPortal:public CObservable
100 {
101 public:
102 void Publish(const string &strContent)
103 {
104 cout<<"portalpublish,content:"<<strContent<<endl;
105 SetChanged();
106 Notify(const_cast<char*>(strContent.c_str()));
107 }
108 };
109 //RSS阅读器,观察者
110 class CRSSReader:public CObserver
111 {
112 public:
113 CRSSReader(conststring&strName):m_strName(strName){}
114 virtual void Update(CObservable *pObs,void *pArg=NULL)
115 {
116 char *pContent=static_cast<char*>(pArg);
117 //观察多个目标
118 if(dynamic_cast<CBloger*>(pObs))
119 {
120 cout<<m_strName<<"updated from bloger,content:"<<pContent<<endl;
121 }
122 elseif(dynamic_cast<CPortal*>(pObs))
123 {
124 cout<<m_strName<<"updated from portal,content:"<<pContent<<endl;
125 }
126 }
127 private:
128 stringm_strName;
129 };
130 //Mail阅读器,观察者
131 class CMailReader:public CObserver
132 {
133 public:
134 CMailReader(conststring &strName):m_strName(strName){}
135 virtual void Update(CObservable *pObs,void *pArg=NULL)
136 {
137 char *pContent=static_cast<char*>(pArg);
138 if(dynamic_cast<CBloger*>(pObs))
139 {
140 cout<<m_strName<<"updated from bloger,content:"<<pContent<<endl;
141 }
142 if(dynamic_cast<CPortal*>(pObs))
143 {
144 cout<<m_strName<<"updated from portal,content:"<<pContent<<endl;
145 }
146 }
147 private:
148 stringm_strName;
149 };
150 /////////////////Main
151 intmain()
152 {
153 //目标(被观察者)
154 CBloger *pBloger=newCBloger();
155 CPortal *pPortal=newCPortal();
156 //观察者.一个观察者可以观察多个目标
157 CRSSReader *pRssReader=new CRSSReader("rssreader");
158 CMailReader *pMailReader=new CMailReader("mailreader");
159 pBloger->Attach(pRssReader);//bloger注册观察者
160 pBloger->Attach(pMailReader);//bloger注册观察者
161 pPortal->Attach(pRssReader);//portal注册观察者
162 pPortal->Attach(pMailReader);//portal注册观察者
163 //博客发布信息
164 pBloger->Publish("博客分享设计模式");
165 cout<<endl;
166 //门户发布信息
167 pPortal->Publish("门户分享设计模式");
168 cout<<"\nportaldetachedmailreader"<<endl;
169 pPortal->Detach(pMailReader);
170 cout<<"portalobserverscount:"<<pPortal->GetObserversCount()<<endl<<endl;
171 pPortal->Publish("门户分享设计模式");
172 system("pause");
173 return0;
174 }

 

设计模式之观察者模式

标签:场景   消息   分离   .com   rtu   else   color   not   virt   

原文地址:http://www.cnblogs.com/qianqiannian/p/6965083.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!