设计模式之观察者模式C++实现

Posted 今天也要努力搬砖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之观察者模式C++实现相关的知识,希望对你有一定的参考价值。

参考书籍《Head First设计模式》

设计模式和设计原则

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

观察者模式遵循的设计原则

为了交互对象之间的松耦合设计而努力。

观察者模式中的类

        提到观察者模式,常常会看到类似于下面的图,图片链接设计模式-观察者模式 C++实现_不很正派的专栏-CSDN博客_c++观察者模式,侵删。下图中包含了观察者中用到的类,其中Subject主题类(主题类有些地方也叫可观察者/被观察者Observable),被观察的类都继承自这个类,该类中声明了实现registerObserver用来添加观察者、removeObserver用来移除观察者、notifyObservers通知观察者的方法。ConcreteSubject具体主题类,继承自主题类。Observer抽象观察者类,声明了update方法,被观察者通知观察者就是通过调用该方法。ConcreteObserver具体观察者继承自抽象观察者类,实现update方法。

        该模式中观察者获取数据有两种方式。一种是“推”的方式,即观察者被动接受数据。主题通知观察者有变更时,就把数据推给观察者。另一种是“拉”的方式,即观察者主动获取数据。主题通知时把自己的引用传给观察者,观察者按照自己需要,使用主题提供的接口获取数据。下面案例中使用的是"拉"的方式。

 案列描述

        气象监测系统的实现。气象站监测气象数据,布告板显示气象数据。有两块布告板,分别显示目前状况(温度、湿度、气压)和天气预报。使用观察者模式,气象站为具体主题,气象板是观察者,当气象数据改变时通知气象板。

代码实现

        声明:类的声明和实现在同一个文件里是个坏习惯,坏习惯,坏习惯,但因为我懒,还是写一起了,大家不要效仿,要引以为戒,要引以为戒,要引以为戒。

        定义主题类Subject,该类中实现了registerObserver、removeObserve、notifyObservers三个函数,代码如下

//主题类
class Subject
public:
	//注册观察者
	void registerObserver(Observer* o)
	
		m_observers.push_back(o);
	
	//移除观察者
	void removeObserver(Observer* o)
	
		for (std::vector<Observer*>::iterator iter = m_observers.begin();
			iter != m_observers.end(); iter++)
		
			if (*iter == o)
			
				m_observers.erase(iter);
				return;
			
		
	
	//通知观察者
	void notifyObservers()
	
		for (std::vector<Observer*>::iterator iter = m_observers.begin();
			iter != m_observers.end(); iter++)
		
			(*iter)->update(this);
		
	
private:
	std::vector<Observer*> m_observers;
;

        定义WeatherData继承自Subject,是观察者模式中的具体主题,其代码如下。其中getter接口是供观察者获取数据使用(采用"拉"的方式主动获取数据)。setter接口是用来设置数据。

//具体主题类
class WeatherData :public Subject
	
public:
	声明获得状态的接口,采用“拉”的方式获取状态时使用
	float getTemperature() return m_temperature; 
	float getHumidity() return m_humidity; 
	float getPressure() return m_pressure; 
	std::string  getPreWeather() return m_preWeather; 

	//设置天气状态,通知观察者
	void setMeasurements(float temperature, float humidity, float pressure, std::string preWeather)
	
		m_temperature = temperature;
		m_humidity = humidity;
		m_pressure = pressure;
		m_preWeather = preWeather;
		notifyObservers();
	
private:
	float m_temperature;
	float m_humidity;
	float m_pressure;
	std::string m_preWeather;
;

观察者类以及具体观察者类的定义如下。主要就是在update方法中获取数据,并调用显示接口

//观察者类
class Observer
public:
	//通过“推”的方式获取数据,参数为各种状态数据
	//virtual void update(float temperature,float humidity,float pressure) = 0;

	//通过“拉”的方式获取数据,参数为subject指针
	virtual void update(Subject* subject) = 0;
;
class Dislay

public:
	virtual void dislay() = 0;
;
//具体观察者,当前温度湿度压强
class CurrentonditionsDisplay :public Observer, public Dislay
public:
	virtual void update(Subject* subject)
	
		WeatherData* weatherData = (WeatherData*)subject;
		m_temperature = weatherData->getTemperature();
		m_humidity = weatherData->getHumidity();
		m_pressure = weatherData->getPressure();
		dislay();
	
	void dislay()
	
		std::cout << "current temperature:" << m_temperature << std::endl;
		std::cout << "current humidity:" << m_humidity << std::endl;
		std::cout << "current pressure:" << m_pressure << std::endl;
	
private:
	float m_temperature;
	float m_humidity;
	float m_pressure;
;

//具体观察者,天气预报气象板
class WeatherPredictionDisplay :public Observer
public:

	virtual void update(Subject* subject)
	
		WeatherData* weatherData = (WeatherData*)subject;
		m_preWeather = weatherData->getPreWeather();
		dislay();

	
	void dislay()
	
		std::cout << "Weather Prediction:" << m_preWeather << std::endl;
	
private:
	std::string m_preWeather;
;

最后在main函数中,写测试代码如下

int main()

	WeatherData* weatherData=new WeatherData();
	CurrentonditionsDisplay* currentonditionsDisplay = new CurrentonditionsDisplay();
	WeatherPredictionDisplay* weatherPredictionDisplay = new WeatherPredictionDisplay();

	//注册为观察者(书上是在构造函数中注册的)
	weatherData->registerObserver(currentonditionsDisplay);
	weatherData->registerObserver(weatherPredictionDisplay);

	//改变天气状态数据
	weatherData->setMeasurements(80, 65, 30, "Sunny");
	weatherData->setMeasurements(82, 79, 29, "Rain");
	weatherData->setMeasurements(78, 90, 28, "Snow");
	
	delete  weatherData;
	delete  currentonditionsDisplay;
	delete  weatherPredictionDisplay;

	system("pause");

执行结果

以上是关于设计模式之观察者模式C++实现的主要内容,如果未能解决你的问题,请参考以下文章

观察者模式C++实现

观察者模式C++实现

观察者模式的线程实现 - C++

C++状态模式,建造者模式,观察者模式,单例模式,备忘录模式实现超市购物

C++观察者模式(发布-订阅)的使用

C++观察者模式(发布-订阅)的使用