观察者模式又称发布-订阅模式,是一种行为型模式。在此种模式中,一个目标物件管理所有相依于它的观察者物件,
并且在它本身的状态改变时主动发出通知。这种模式通常用来实现事件处理系统。
观察者模式完美的将观察者和被观察的对象分离开,在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
观察者模式定义了对象间的一种一对多的依赖关系,以便一个对象状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
实现方式:
观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。实现的时候要注意,
观察者和被观察对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察对象之间紧密的耦合起来,
从根本上违反面向对象的设计的原则。无论是观察者“观察”被观察对象,还是被观察对象将自己的改变“通知”观察者,都不应该直接调用。
比较直观的一种是“注册-通知-撤销注册"的形式。
观察者(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 }
学习无他法,唯有持之以恒