C++观察者模式(Observer Pattern)

意图

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。

动机

将一个系统分割成一系列相互协作的类有一个常见的副作用:需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,因为这样降低了它们的可重用性。

适用性

  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
  • 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
  • 当一个对象必须通知其他对象,而它又不能假定其他对象是谁。换言之。你不希望这些对象是紧密耦合的。

类图

在这里插入图片描述

例子场景

气象观察站追踪温度、湿度、气压数值,需要有一个布告板,分别显示目前的状况(温度、湿度、气压),每当有新的数据生成,布告板需要实时更新。

实现

Subject.h

#pragma once

class Observer;
class Subject
{
public:
	Subject();
	virtual void registerObserver(Observer* pObserver) = 0;
	virtual void removeObserver(Observer* pObserver) = 0;
	virtual void notifyObserver() = 0;
};

Subject.cpp

#include "Subject.h"

Subject::Subject()
{
}

Observer.h

#pragma once

class Observer
{
public:
	Observer();
	virtual void update(const float& temperature, const float& humidity, const float& pressure) = 0;
};

Observer.cpp

#include "Observer.h"

Observer::Observer()
{

}

WeatherData.h

#pragma once

#include "Subject.h"
#include <vector>

class Observer;
class WeatherData : public Subject
{
public:
	WeatherData();
	void registerObserver(Observer* pObserver) override;
	void removeObserver(Observer* pObserver) override;
	void notifyObserver() override;
	void measurementsChanged();
	void setMeasurements(const float& temperature, const float& humidity, const float& pressure);
private:
	std::vector<Observer*> m_observers;
	float m_temperature;
	float m_humidity;
	float m_pressure;
};

WeatherData.cpp

#include "WeatherData.h"
#include "Observer.h"

WeatherData::WeatherData()
	: m_temperature(0)
	, m_humidity(0)
	, m_pressure(0)
{
}

void WeatherData::registerObserver(Observer* pObserver)
{
	m_observers.push_back(pObserver);
}

void WeatherData::removeObserver(Observer* pObserver)
{
	for (size_t i = 0; i < m_observers.size(); ++i)
	{
		if (pObserver == m_observers[i])
		{
			m_observers.erase(m_observers.begin() + i);
			break;
		}
	}
}

void WeatherData::notifyObserver()
{
	for (size_t i = 0; i < m_observers.size(); ++i)
	{
		m_observers[i]->update(m_temperature, m_humidity, m_pressure);
	}
}

void WeatherData::measurementsChanged()
{
	notifyObserver();
}

void WeatherData::setMeasurements(const float& temperature, const float& humidity, const float& pressure)
{
	this->m_temperature = temperature;
	this->m_humidity = humidity;
	this->m_pressure = pressure;
	measurementsChanged();
}

CurrentConditionsDisplay.h

#pragma once

#include "Observer.h"

class Subject;
class CurrentConditionsDisplay : public Observer
{
public:
	CurrentConditionsDisplay(Subject* pWeatherData);
	void update(const float& temperature, const float& humidity, const float& pressure) override;
private:
	void display();
	float m_temperature;
	float m_humidity;
	Subject* m_pWeatherData;
};

CurrentConditionsDisplay.cpp

#include "CurrentConditionsDisplay.h"
#include "Subject.h"
#include <iostream>


CurrentConditionsDisplay::CurrentConditionsDisplay(Subject* pWeatherData)
	: m_temperature(0)
	, m_humidity(0)
	, m_pWeatherData(pWeatherData)
{
	m_pWeatherData->registerObserver(this);
}

void CurrentConditionsDisplay::update(const float& temperature, const float& humidity, const float& pressure)
{
	this->m_temperature = temperature;
	this->m_humidity = humidity;
	display();
}

void CurrentConditionsDisplay::display()
{
	std::cout << "Current conditions: " << m_temperature << std::endl;
	std::cout << "Humidity: " << m_humidity << std::endl;
}

main.cpp

#include "WeatherData.h"
#include "CurrentConditionsDisplay.h"
#include <memory>

int main()
{
	std::shared_ptr<WeatherData> pWeatherData = std::make_shared<WeatherData>();
	std::shared_ptr<CurrentConditionsDisplay> pCurrentConditionsDisplay = std::make_shared<CurrentConditionsDisplay>(pWeatherData.get());
	pWeatherData->setMeasurements(2.3, 1.0, 4.5);
	pWeatherData->setMeasurements(3.5, 7.0, 4.1);

	return 0;
}

输出

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值