HeadFirst设计模式 之 C++实现(二):Observer(观察者模式)
观察者模式是最经常使用的设计模式之中的一个,【对象之间多对一的依赖关系,当一个对象发生变化时,其会通知全部依赖它的对象】。拿订阅报纸和发行报社打例如,报社採集到news制作新的报纸,派送给订阅的客户。以此把最新的消息告知客户。所以。出版社 + 订阅者 = 观察者模式。
这样的一对多的关系,也即“一个”主题、“多个”观察者可以使得观察者只了解主题推送的消息但不知晓当中的细节,而主题握有观察者列表但不干涉到观察者的个人隐私。所以。它们之间相互有交互,但不紧密,不清楚对方的细节。改变主题或者观察者随意一方。并不会影响到对方。
这就是,设计原则之四:为了交互对象之间的松耦合设计而努力。
以下我们来看气象站的建设,满足:有气象数据更新时。通知用户。用户能够在布告板上显示出更新信息。
这个是典型的推送服务(Push),一有新信息就发送给观察者,可是有的时候过于频繁的推送会给用户带来非常多不须要的“垃圾”信息,所以设计主动的询问(Pull)相同非常有意义。
然后是我自己用C++实现的气象站模型,有疏漏的地方请不吝赐教:
<span style="font-size:12px;">// Observer Pattern.h #include <list> #include <string> class Observer; // 实现主题接口 class Subject { public: virtual ~Subject(); virtual registerObserver(Subject *obv); virtual removeObserver(Subject *obv); virtual notifyObserver(); // 主题信息改变,由此通知全部观察者"推Push" protected: Subject(); // 限制仅仅能子类构造 }; class WeatherData : public Subject { private: list<Observer *> *m_observers; float m_temperature; float m_humidity; float m_pressure; public: WeatherData(); virtual ~ WeatherData(); virtual registerObserver(Subject *obv); virtual removeObserver(Subject *obv); virtual notifyObserver(); float getTemperature();<span style="white-space:pre"> </span>// 这是让用户自己get想要的信息。主题仅仅须要开放对应的接口就可以 float getHumidity(); float getPressure(); void measureChanged(); }; // 实现观察者接口、显示接口 class Observer { public: Observer(); virtual ~Observer(); virtual void update(float temp, float humidity, float pressure) = 0; }; class DisplayElement { public: DisplayElement(); virtual ~DisplayElement(); virtual void display() = 0; }; // 多重继承 class CurrentConditionsDisplay : public Observer, public DisplayElement { public: CurrentConditionsDisplay(); virtual ~CurrentConditionsDisplay(); virtual void update(float temp, float humidity, float pressure); virtual void display(Subject sub); private: Subject *m_sub; float m_temp; float m_humidity; }; class StaticsDisplay : public Observer, public DisplayElement { public: StaticsDisplay(); virtual ~StaticsDisplay(); virtual void update(float temp, float humidity, float pressure); virtual void display(Subject sub); private: Subject *m_sub; float avg_temp; float max_temp; float min_temp; }; class ForecastDisplay : public Observer, public DisplayElement { public: ForecastDisplay(); virtual ~ForecastDisplay(); virtual void update(float temp, float humidity, float pressure); virtual void display(Subject sub); private: Subject *m_sub; };</span>
OBSERVER — 想知道咱们公司最新MM情报吗?增加公司的MM情报邮件组即可了,tom负责搜集情报,他发现的新情报不用一个一个通知我们,直接公布给邮件组,我们作为订阅者(观察者)就能够及时收到情报啦
观察者模式:观察者模式定义了一种一队多的依赖关系。让多个观察者对象同一时候监听某一个主题对象。
这个主题对象在状态上发生变化时,会通知全部观察者对象,使他们可以自己主动更新自己。
<span style="font-size:12px;">// Observer Pattern(观察者模式) #include <iostream> #include "ObserverPattern.h" using std::cout; using std::endl; // 主题接口 Subject::~Subject() { } // 气象站的主题接口实现 WeatherData::WeatherData() { m_observers = new list<Observer *>; } WeatherData::~ WeatherData() { } WeatherData::registerObserver(Subject *obv) { if(nullptr != obv) { m_observers->push_front(obv); } } WeatherData::removeObserver(Subject *obv) { if(nullptr != obv) { m_observers->remove(obv); } } WeatherData::notifyObserver() { list<Observer *>::iterator iter; for(; iter!=m_observers->end(); iter++) // 注意呢,迭代器的使用 { (*iter)->update(m_temperature, m_humidity, m_pressure); } } float WeatherData::getTemperature() { return m_temperature; } float WeatherData::getHumidity() { return m_humidity; } float WeatherData::getPressure() { return m_pressure; } void WeatherData::measureChanged() { notifyObserver(); // 主题信息更新,通知全部观察者 } // 观察者和显示的接口 CurrentConditionsDisplay::CurrentConditionsDisplay(Subject *sub) { m_sub = sub; m_sub->registerObserver(this); } CurrentConditionsDisplay::~CurrentConditionsDisplay() { m_sub->removeObserver(this); if(nullptr != m_sub) delete m_sub; } void CurrentConditionsDisplay::update(float temp, float humidity, float pressure) { m_temp = temp; m_humidity = humidity; display(); } void CurrentConditionsDisplay::display(Subject sub) { cout << "Current condition: "<< m_temp << "F degrees and " << m_humidity << "%% humidity" << endl; } // 其它两个接口实现的类也是相似的</span>
还有生活中常见的样例:对同一组数据进行统计分析时候。我们希望可以提供多种形式的表示(比如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然须要当数据改变的时候,全部的统计的显示都可以同一时候改变。
重要的是,【会活用设计模式】。
转载请注明出处:http://blog.csdn.net/aall3210_tsingloon/article/details/27712851