观察者模式实现 in C++

版权声明:本文为博主原创文章,如有需要,可以转载,但请注明出处。 https://blog.csdn.net/xunye_dream/article/details/84718963

对于程序员来说,最好的交流应该是代码了。直接上代码吧,如有更好的实现方式,或代码有不妥的地方,也请大神赐教吧。

一、目录结构

二、接口部分代码

1、主题——Subject.h

#ifndef INC_INTERFACE_SUBJECT_H_
#define INC_INTERFACE_SUBJECT_H_

struct Observer;

struct Subject
{
	virtual ~Subject() {};
	virtual void registerObserver(const Observer* o) = 0;
	virtual void removeObserver(const Observer* o) = 0;
	virtual void notifyObservers() = 0;
};

#endif

2、订阅者——Observer.h

#ifndef INC_INTERFACE_OBSERVER_H_
#define INC_INTERFACE_OBSERVER_H_

struct Observer
{
	virtual ~Observer() {}
	virtual void update(float temp, float humidity, float pressure) = 0;
};

#endif

3、显示——DisplayElement.h

#ifndef INC_INTERFACE_DISPLAYELEMENT_H_
#define INC_INTERFACE_DISPLAYELEMENT_H_

struct DisplayElement
{
	virtual ~DisplayElement() {}
	virtual void display() = 0;
};

#endif

三、实现部分

1、发布者——WeatherData.h

#ifndef INC_PUBLISHER_WEATHERDATA_H_
#define INC_PUBLISHER_WEATHERDATA_H_

#include "interface/Observer.h"
#include "interface/Subject.h"
#include <vector>
#include <algorithm>

using std::vector;

struct WeatherData : Subject
{
	WeatherData() : temperature(0), humidity(0), pressure(0)
	{
		observers.clear();
	}

	void registerObserver(const Observer* o) override
	{
		observers.push_back(o);
	}

	void removeObserver(const Observer* o) override
	{
		auto it = std::find(observers.begin(), observers.end(), o);
		if (it != observers.end())
		{
			observers.erase(it);
		}
	}

	void setMeasurements(float temperature, float humidity, float pressure)
	{
		this->temperature = temperature;
		this->humidity = humidity;
		this->pressure = pressure;
		measurementsChanged();
	}

private:
	void notifyObservers() override
	{
		for (auto observer : observers)
		{
			const_cast<Observer*>(observer)->update(temperature, humidity, pressure);
		}
	}

	void measurementsChanged()
	{
		notifyObservers();
	}

private:
	float temperature;
	float humidity;
	float pressure;
	vector<const Observer*> observers;
};


#endif

2、订阅者——CurrentConditionsDisplay.h

#ifndef INC_SUBSCRIBER_CURRENTCONDITIONSDISPLAY_H_
#define INC_SUBSCRIBER_CURRENTCONDITIONSDISPLAY_H_

#include "interface/Observer.h"
#include "interface/DisplayElement.h"
#include "interface/Subject.h"
#include <iostream>

struct CurrentConditionsDisplay : Observer
                                , private DisplayElement
{
	CurrentConditionsDisplay(Subject& weatherData) : temperature(0), humidity(0)
                                                   , weatherData(weatherData)
	{
		this->weatherData.registerObserver(this);
	}

	void update(float temperature, float humidity, float pressure) override
	{
		this->temperature = temperature;
		this->humidity = humidity;
		display();
	}

private:
	void display() override
	{
		std::cout << "Current conditions: "
				  << temperature << "F degrees and "
				  << humidity << "% humidity" << std::endl;
	}

private:
	float temperature;
	float humidity;
	Subject& weatherData;
};

#endif

四、使用

1、main.cpp

#include <iostream>
#include "publisher/WeatherData.h"
#include "subscriber/CurrentConditionsDisplay.h"

using namespace std;

int main(int argc, char **argv)
{
	WeatherData weatherData;
	CurrentConditionsDisplay currentDisplay(weatherData);

	weatherData.setMeasurements(80, 65, 30.4f);
	weatherData.setMeasurements(99, 45, 23.4f);

	weatherData.removeObserver(&currentDisplay);

	weatherData.setMeasurements(99, 45, 23.4f);

	return 0;
}

2、显示

五、总结

        从上述的接口实现部分可以看出,观察者模式的实现符合面向接口编程的原则。

       发布者和订阅者是1对多的关系。

       接口类的实现,记得添加虚析构函数。

猜你喜欢

转载自blog.csdn.net/xunye_dream/article/details/84718963