观察者模式又叫发布-订阅(Publish/SubScribe)模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
#include <iostream> #include <list> using namespace std; /*Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。 这个接口叫做更新接口。抽象观察者一般用一个抽象类或者一个接口实现。 更新接口通常包含一个Updata()方法,叫做更新方法。*/ class Observer { public: virtual void Update()=0; }; /*Subject类,可翻译为主题或抽象通知者,一般用一个抽象类或者一个接口实现。 他把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。 抽象主题提供一个接口,可以增加和删除观察者对象*/ class Subject { private: list<Observer *> observers; string subjectState; public: //增加观察者 void Attach(Observer *observer) { observers.push_back(observer); } //移除观察者 void Detach(Observer *observer) { observers.remove(observer); } //通知 void Notify() { list<Observer*>::iterator iter=observers.begin(); for(;iter!=observers.end();iter++) { (*iter)->Update(); } } /*virtual void setStatus(string s) { this->subjectState=s; } virtual string GetState() { return this->subjectState; }*/ }; /*ConcreteSubject类,叫做具体主题或者具体通知者,将有关状态存入具体观察着对象; 在具体主题的内部状态变化时,给所有登记过观察者发出通知。具体主题角色通常用一个具体子类实现*/ class ConcreteSubject:public Subject { private: string subjectState; public: void setStatus(string value) { this->subjectState=value; } string GetState() { return this->subjectState; } }; /*ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。 具体观察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现*/ class ConcreteObserver:public Observer { private: string m_name; string observerState; ConcreteSubject *sub; public: ConcreteObserver(ConcreteSubject *subj,string name) { this->sub=subj; this->m_name=name; } void Update() { this->observerState=sub->GetState(); cout << "观察者" << this->m_name << "的新状态是" << this->observerState << endl; } }; int main() { ConcreteSubject *s = new ConcreteSubject(); s->Attach(new ConcreteObserver(s,"X")); s->Attach(new ConcreteObserver(s,"Y")); s->Attach(new ConcreteObserver(s,"Z")); s->setStatus("ABC"); s->Notify(); return 0; }
观察模式的动机是将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了威化一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。而观察者模式的关键对象是主题Subject和观察者Observer,一个Subject可以有任意数目的依赖它的Observer,一旦Subject的状态发生了改变,所有的Observer都可以通知到。Subject发出通知时并不需要知道谁是它的观察者,也就是说,具体观察者是谁,它根本不需要知道。而任何一个具体观察者不知道也不需要知道其他观察者模式的存在。
当一个对象的改变需要同时改变其他对象,而且他不知道具体有多少对象有待改变时,应该考虑使用观察者模式。当一个抽象模型有两方面,其中一个方面依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使他们各自独立地改变和复用。
总的来说,观察者模式所做的工作其实就是在解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
举个例子,下面是代码结构图:
#include <iostream> #include <list> using namespace std; class Subject; class Observer { public: virtual void Update()=0; }; class Subject { private: string m_status; public: virtual void Attach(Observer *obser)=0; virtual void Detach(Observer *obser)=0; virtual void Notify()=0; virtual void SetStatus(string st)=0; virtual string GetStatus()=0; }; class Boss:public Subject { private: list<Observer *> observer; string action; public: void Attach(Observer *obser) { observer.push_back(obser); } void Detach(Observer *obser) { observer.remove(obser); } void Notify() { list<Observer*>::iterator iter=observer.begin(); for(;iter!=observer.end();iter++) { (*iter)->Update(); } } void SetStatus(string stat) { this->action=stat; } string GetStatus() { return this->action; } }; class Secretary:public Subject { private: list<Observer *> observer; string action; public: void Attach(Observer *obser) { observer.push_back(obser); } void Detach(Observer *obser) { observer.remove(obser); } void Notify() { list<Observer*>::iterator iter=observer.begin(); for(;iter!=observer.end();iter++) { (*iter)->Update(); } } void SetStatus(string stat) { this->action=stat; } string GetStatus() { return this->action; } }; class StockObserver:public Observer { private: string m_name; Subject *subject; string m_status; public: StockObserver(string name,Subject *sub) { this->m_name=name; this->subject=sub; } void Update() { this->m_status=subject->GetStatus(); cout << this->m_status << this->m_name << "关闭股票行情,继续工作!" << endl; } }; class NBAObserver:public Observer { private: string m_name; Subject *subject; string m_status; public: NBAObserver(string name,Subject *sub) { this->m_name=name; this->subject=sub; } void Update() { this->m_status=subject->GetStatus(); cout << this->m_status << this->m_name << "关闭NBA直播,继续工作!" << endl; } }; int main() { Boss *huhansan=new Boss(); StockObserver *tongshi1=new StockObserver("Tom",huhansan); NBAObserver *tongshi2=new NBAObserver("Jack",huhansan); huhansan->Attach(tongshi1); huhansan->Attach(tongshi2); huhansan->Detach(tongshi1); huhansan->SetStatus("我胡汉三回来了!"); huhansan->Notify(); return 0; }
【设计模式】——观察者模式
时间: 2024-11-07 14:37:45