设计模式之观察者模式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++观察者模式(发布-订阅)的使用

js设计模式之实现观察者模式实例代码

设计模式之单例模式

设计模式之观察者模式