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

目录

类关系图: 

一、定义接口 

1.1 定义主题接口:  CSubject

 1.2 定义观察者接口   CObserver

 1.3 定义显示接口  CDisplayElement

二、在CWeatherData 中实现主题接口

三、建立布告板 CCurrentConditionsDisplay 

四、启动气象站 CWeatherStation

参考资料:


摘要

  观察者设计模式可以类比为:电子报纸出版社为主题(Subject),而订阅电子报纸的人为观察者(Observer),只要有新的事件,出版社就会给每一个订阅者发送信息。观察者可以注册订阅、取消订阅,而出版社可以通知所有的订阅者。

 

 

 

类关系图: 

一、定义接口 

1.1 定义主题接口:  CSubject

#pragma once
#include "Observer.h"

//CSubject:出版者
//接口类
class CSubject
{
public:
	CSubject(void);
	~CSubject(void);
public:
	virtual void RegisterObserver(CObserver* pObserver) = 0;
	virtual void RemoveObserver(CObserver* pObserver)   = 0;
	virtual void NotifyObservers()  = 0;


};
#include "stdafx.h"
#include "Subject.h"
#include "Observer.h"


CSubject::CSubject(void)
{
}


CSubject::~CSubject(void)
{
}

 1.2 定义观察者接口   CObserver

#pragma once

//CObserver:订阅者
//接口
class CObserver
{
public:
	CObserver(void);
	virtual ~CObserver(void);
public:
	virtual void Update(double dTemperature,double dTumidity,double dPressure) = 0; //只有一个Updete方法
};

 

#include "stdafx.h"
#include "Observer.h"


CObserver::CObserver(void)
{
}


CObserver::~CObserver(void)
{
}

 1.3 定义显示接口  CDisplayElement

#pragma once
//接口
class CDisplayElement
{
public:
	CDisplayElement(void);
	virtual ~CDisplayElement(void);
public:
	virtual void Display() = 0; 
};

#include "stdafx.h"
#include "DisplayElement.h"


CDisplayElement::CDisplayElement(void)
{
}


CDisplayElement::~CDisplayElement(void)
{
}


二、在CWeatherData 中实现主题接口

#pragma once
#include "afx.h"
#include <vector>
#include "Observer.h"
#include "Subject.h"

//主题是正在拥有数据的人
//在CWeatherData实现CSubject的接口
class CWeatherData : public CSubject
{
public:
	CWeatherData(void);
	virtual ~CWeatherData(void);
	void Init();
public:
	virtual void RegisterObserver(CObserver* pObserver);
	virtual void RemoveObserver(CObserver* pObserver);
	virtual void NotifyObservers();

	void MeasurementsChanged();
	void SetMeasurements(const double dTemperature,const double dHumitity,const double dPressure);

	double GetTemperature() const;
	double GetHumidity() const;
	double GetPressure() const;
private:
	std::vector<CObserver*> m_pArrObserver;  //无数个观察者(订阅者)
	double m_dTemperature;
	double m_dHumidity;
	double m_dPressure;

};

#include "stdafx.h"
#include "WeatherData.h"


CWeatherData::CWeatherData(void)
{
	Init();
}


CWeatherData::~CWeatherData(void)
{
	for (auto it = m_pArrObserver.begin(); it != m_pArrObserver.end(); it++)
	{
		if ((*it) != nullptr)
		{
			delete *it;
			(*it) = nullptr;
		}
	}
}


void CWeatherData::Init()
{
	m_dTemperature = 0.0;
	m_dHumidity = 0.0;
	m_dPressure = 0.0;
}

//注册观察者
void CWeatherData::RegisterObserver(CObserver* pObserver)
{
	m_pArrObserver.push_back(pObserver);
}

//删除观察者
void CWeatherData::RemoveObserver(CObserver* pObserver)
{
	for (auto it = m_pArrObserver.begin(); it != m_pArrObserver.end(); it++)
	{
		if (*it == pObserver)
		{
			m_pArrObserver.erase(it);
		}
	}

}

//通知观察者
void CWeatherData::NotifyObservers()
{
	for (auto it = m_pArrObserver.begin(); it != m_pArrObserver.end(); it++)
	{
		(*it)->Update(m_dTemperature, m_dHumidity, m_dPressure);
	}
}

//信息发生变化
void CWeatherData::MeasurementsChanged()
{
	NotifyObservers();
}

void CWeatherData::SetMeasurements(const double dTemperature,const double dHumitity,const double dPressure)
{
	m_dTemperature = dTemperature;
	m_dHumidity = dHumitity;
	m_dPressure = dPressure;

	MeasurementsChanged();
}

double CWeatherData::GetTemperature() const
{
	return m_dTemperature;
}

double CWeatherData::GetHumidity() const
{
	return m_dHumidity;
}

double CWeatherData::GetPressure() const
{
	return m_dPressure;
}

三、建立布告板 CCurrentConditionsDisplay 

#pragma once
#include "Observer.h"
#include "DisplayElement.h"
#include "Subject.h"

//根据CWeatherData对象显示当前观测值
class CCurrentConditionsDisplay : public CObserver, public CDisplayElement
{
public:
	CCurrentConditionsDisplay(CSubject* pWeatherData);
	virtual ~CCurrentConditionsDisplay(void);
public:
	void Update(double dTemperature,double dTumidity,double dPressure);
	void Display();
private:
	CSubject* m_pWeatherData;

	double m_dTemperature;
	double m_dHumidity;
	double m_dPressure;
};

#include "stdafx.h"
#include "CurrentConditionsDisplay.h"
#include "WeatherData.h"


CCurrentConditionsDisplay::CCurrentConditionsDisplay(CSubject* pWeatherData)
{
	m_pWeatherData = new CWeatherData; 
	*m_pWeatherData = *pWeatherData;
	ASSERT(m_pWeatherData);
	if (m_pWeatherData != nullptr)
	{
		m_pWeatherData->RegisterObserver(this);		
	}
}

CCurrentConditionsDisplay::~CCurrentConditionsDisplay(void)
{
	delete m_pWeatherData;
}

void CCurrentConditionsDisplay::Update(double dTemperature,double dTumidity,double dPressure)
{
	m_dTemperature = dTemperature;
	m_dHumidity = dTumidity;
	m_dPressure = dPressure;

	Display();
}

void CCurrentConditionsDisplay::Display()
{
	CString str;
	str.Format(_T("Current conditions: %.1f degrees , Humidity: %.1f, Pressure : %.1f"), m_dTemperature, m_dHumidity, m_dPressure);
	AfxMessageBox(str,MB_OK);
}

四、启动气象站 CWeatherStation

#pragma once
class CWeatherStation
{
public:
	CWeatherStation(void);
	~CWeatherStation(void);
public:
	void Main();
};

#include "stdafx.h"
#include "WeatherStation.h"
#include "WeatherData.h"

#include <memory>
#include "CurrentConditionsDisplay.h"
#include "StaticDisplay.h"
#include "ForcastDisplay.h"
#include "Observer.h"

CWeatherStation::CWeatherStation(void)
{
}


CWeatherStation::~CWeatherStation(void)
{
}

void CWeatherStation::Main()
{
	CWeatherData* pWeatherData = new CWeatherData;

	//当前天气状况布告板
	CCurrentConditionsDisplay* pCurrentDisplay = new CCurrentConditionsDisplay(pWeatherData);

	//天气统计布告板
	CStatisticsDisplay* pStatisticsDisplay = new CStatisticsDisplay(pWeatherData);
	pWeatherData->RegisterObserver(pStatisticsDisplay);

	//天气预报布告板
	CForcastDisplay* pForcastDisplay = new CForcastDisplay(pWeatherData);
	pWeatherData->RegisterObserver(pForcastDisplay);

	pWeatherData->SetMeasurements(80.0, 65.0, 30.4);
	pWeatherData->SetMeasurements(82.0, 70.0, 29.2);
	pWeatherData->SetMeasurements(78.0, 90.0, 29.2);

	delete pWeatherData;
}

五、完整代码实现

https://github.com/mc-liyanliang/Design-patterns/tree/master/Observer%20Pattem

六、参考资料:

《Head First设计模式》 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值