head first设计模式学习笔记(二)——观察者模式 C++实现

今天为大家介绍《head first设计模式》中的观察者模式的C++实现代码。

首先定义三个抽象类Observer、Subject和DisplayElement,代码如下。

//Observer.h
#ifndef _OBSERVER_H_
#define _OBSERVER_H_
#include"head.h"
class Observer
{
public:
	Observer(){}
	virtual ~Observer(){}//必须的有定义,即{}
	virtual void update(float temp,float humi,float press)=0;
};

#endif
//Subject.h
#ifndef _SUBJECT_H_
#define _SUBJECT_H_
#include"head.h"
class Subject
{
public:
	virtual void registerObserver(Observer* O)=0;
	virtual void removeObserver(Observer* O)=0;
	virtual void notifyObservers() const=0;
};

#endif
//DisplayElement.h
#ifndef _DISPLAYELEMENT_H_
#define _DISPLAYELEMENT_H_
#include"head.h"
class DisplayElement
{
public:
	DisplayElement(){}
	virtual ~DisplayElement()=0{}//必须得有定义,即{}
	virtual void display() const=0;
};


#endif

然后是主题类Subject的派生类WeatherData

//WeatherData.h
#ifndef _WEATHERDATA_H_
#define _WEATHERDATA_H_
#include"head.h"
class WeatherData:public Subject
{
private:
	list< Observer*> obs;
	float temperature;
	float humidity;
	float pressure;
private:
	WeatherData(const WeatherData&);
	WeatherData& operator=(const WeatherData&);
public:
	WeatherData():temperature(0.0),humidity(0.0),
		pressure(0.0){
			cout<<"WeatherData"<<endl;
	}
	~WeatherData()
	{
		cout<<"~WeatherData"<<endl;
	}
	virtual void registerObserver(Observer* O)
	{
		assert(O);
		obs.push_back(O);
	}
	virtual void removeObserver(Observer* O)
	{
		assert(O);
		obs.remove(O);
	}
	virtual void notifyObservers() const
	{
		list< Observer*>::const_iterator iter=obs.begin();
		for(;iter!=obs.end();iter++)
		{
			(*iter)->update(temperature,humidity,pressure);
		}
	}
	void measurementsChanged()
	{
		notifyObservers();
	}

	void setMeasurements(float temp, float humi, float press) 
	{
		temperature=temp;
		humidity=humi;
		pressure=press;
		measurementsChanged();
	}

	float getTemperature() const
	{
		return temperature;
	}
	float getHumidity() const
	{
		return humidity;
	}
	float getPressure() const
	{
		return pressure;
	}
};

#endif

下面是同时继承Observer和DisplayElement的三个派生类。

//CurrentConditionsDisplay.h
#ifndef _CURRENTCONDITIONSDISPLAY_H_
#define _CURRENTCONDITIONSDISPLAY_H_
#include"head.h"
class CurrentConditionsDisplay:public Observer,public DisplayElement
{
private:
	shared_ptr<Subject> Weat;
	float temperature;
	float humidity;
	float pressure;
public:
	CurrentConditionsDisplay(shared_ptr<Subject> W):Weat(W),
	  temperature(0.0),humidity(0.0),pressure(0.0)
	{
		assert(Weat);
		cout<<"CurrentConditionsDisplay"<<endl;
		Weat->registerObserver(this);
	}
	 ~CurrentConditionsDisplay()
	 {
		 cout<<"~~CurrentConditionsDisplay"<<endl;
		 Weat->removeObserver(this);
	 }
	 void update(float temp,float humi,float press)
	 {
		 temperature=temp;
		 humidity=humi;
		 pressure=press;
		 display();
	 }
	 void display() const
	 {
		 cout<<"the temperature is "<<temperature<<endl;
		 cout<<"the humidity is "<<humidity<<endl;
		 cout<<"the pressure is "<<pressure<<endl;
	 }
};

#endif
//StatisticsDisplay.h
#ifndef _STATISTICSDISPLAY_H_
#define _STATISTICSDISPLAY_H_
#include"head.h"
class StatisticsDisplay:public Observer,public DisplayElement
{
private:
	shared_ptr<Subject> Weat;
	float maxtemp;
	float mintemp;
	float sumtemp;
	int numread;
public:
	StatisticsDisplay(shared_ptr<Subject> W):Weat(W),
	  maxtemp(0.0),mintemp(200.0),sumtemp(0.0),numread(0)
	{
		assert(Weat);
		cout<<"StatisticsDisplay"<<endl;	
		Weat->registerObserver(this);
	}
	~StatisticsDisplay()
	{
		Weat->removeObserver(this);
		cout<<"~StatisticsDisplay"<<endl;
	}
	void update(float temp,float humi,float press)
	{
		sumtemp+=temp;
		numread++;
		if(temp>maxtemp)
			maxtemp=temp;
		if(temp<mintemp)
			mintemp=temp;
		display();
	}
	void display() const
	{
		cout<<"maxtemp is "<<maxtemp<<endl;
		cout<<"mintemp is "<<mintemp<<endl;
		cout<<"avertemp is "<<sumtemp/numread<<endl;
	}
};

#endif
//ForecastDisplay.h
#ifndef _FORECASTDISPLAY_H_
#define _FORECASTDISPLAY_H_
#include"head.h"
class ForecastDisplay:public Observer,public DisplayElement
{
private:
	shared_ptr<Subject> Weat;
	float Curr_press;
	float Last_press;
public:
	ForecastDisplay(shared_ptr<Subject> W):Weat(W),
		Curr_press(0.0),Last_press(0.0)
	{
		assert(Weat);
		cout<<"ForecastDisplay!"<<endl;
		Weat->registerObserver(this);
	}
	~ForecastDisplay()
	{
		cout<<"~~~ForecastDisplay"<<endl;
		Weat->removeObserver(this);
	}
	void update(float temp,float humi,float press)
	{
		Last_press=Curr_press;
		Curr_press=press;
		display();
	}
	void display() const
	{
		float comp=Last_press-Curr_press;
		if(!(comp>-0.000001&&comp<0.000001))
		{
			if(comp>0.0)
				cout<<"The pressure is declining"<<endl;
			else
				cout<<"The pressure is rising"<<endl;
		}
		else
			cout<<"The pressure is constant"<<endl;

	}
};
#endif

然后是包括本程序头文件的文件。

//head.h
#ifndef _HEAD_H_
#define _HEAD_H_

#include<list>
#include<iostream>
#include<assert.h>
#include<memory>
using namespace std;

#include"DisplayElement.h"
#include"Observer.h"
#include"Subject.h"
#include"CurrentConditionsDisplay.h"
#include"StatisticsDisplay.h"
#include"ForecastDisplay.h"

#include"WeatherData.h"

#endif

最后是主函数实现。

//main.cpp
#include"head.h"
int main()
{
	//程序是这样设计的:
	//1.先创建一个WeatherData对象(主题),
	//2.然后通过主题对象(WeatherData)作为观察者构造函数的参数构造
	//观察者对象(包括CurrentConditionsDisplay、StatisticsDisplay以及  )
	//3.在创建观察者对象时,在其构造函数中把其加入到主题中。所以在观察者类中
	//将包括一个私有的WeatherData类成员,即这就是所谓的组合类。
	//4.然后WeatherData对象调用setMeasurements函数时,将会最终调用观察者类的update函数
	//(这是由于WeatherData类中有list<Observer*>的私有类型,拿来存放观察者的多个类),同时
	//而在update函数中将调用display函数,最后将WeatherData对象调用setMeasurements函数的设置的结果
	//展现到界面上。
	//5.在观察者类中调用析构函数时将从主题中移除。
	shared_ptr<WeatherData> weat(new WeatherData);
	shared_ptr<CurrentConditionsDisplay> curr(new CurrentConditionsDisplay(weat));
	shared_ptr<StatisticsDisplay> statis(new StatisticsDisplay(weat));
	ForecastDisplay fore(weat);
	weat->setMeasurements(80.0,70.0,90.0);
	weat->setMeasurements(81.0,75.0,89.0);
	weat->setMeasurements(81.0,75.0,89.0);
	return 0;
}







 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值