• 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>


    对于Java中有已经实现的Observable类和Observer,之后将继续学习....  也即MVC中的观察者模式。最大的差别是将主题接口设计成了一个base class,这么做是有缺点的,不适合代码的使用和复用,最好的办法就是设计成接口,多用组合,针对接口编程。但这里仍然放出Java的UML图供学习:



    还有生活中常见的样例:对同一组数据进行统计分析时候。我们希望可以提供多种形式的表示(比如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然须要当数据改变的时候,全部的统计的显示都可以同一时候改变。

    重要的是,【会活用设计模式】


    转载请注明出处:http://blog.csdn.net/aall3210_tsingloon/article/details/27712851

  • 相关阅读:
    kali linux DVWA config 问题解决方案
    HashMap&线程
    Synchronized和java.util.concurrent.locks.Lockde区别联系
    线程池
    信息嗅探
    java子类对象和成员变量的隐写&方法重写
    Java中Super和final关键字以及异常类
    523. Continuous Subarray Sum
    494. Target Sum
    477. Total Hamming Distance
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5182945.html
Copyright © 2020-2023  润新知