摘要
《Head First 设计模式》书中第2章——观察者模式(Observer Pattern)的C++代码实现。
观察者模式(Observer Pattern):类似于订阅报纸。定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
实现代码
// 《Head First 设计模式》C++实现【观察者模式(Observer Pattern)】
// 定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。
#include <iostream>
#include <set>
using namespace std;
//接口
class Observer
{
public:
virtual void update(float temperature, float humidity, float pressure) = 0;
};
class DisplayElement
{
public:
virtual void display() = 0;
};
class Subject
{
public:
virtual void RegisterObserver(Observer *p_observer) = 0;
virtual void RemoveObserver(Observer *p_observer) = 0;
virtual void NotifiyObserver() = 0;
};
//对象
class WeatherDate : public Subject
{
private:
set<Observer *> observers;
float temperature;
float humidity;
float pressure;
public:
WeatherDate()
{
//TODO:
}
void RegisterObserver(Observer *p_observer)
{
//if 不存在该observer则添加
observers.insert(p_observer);
}
void RemoveObserver(Observer *p_observer)
{
//删除observer
observers.erase(p_observer);
}
void NotifiyObserver()
{
//遍历所有observer的update
set<Observer *>::iterator it;
for (it = observers.begin(); it != observers.end(); ++it)
{
(*it)->update(temperature, humidity, pressure);
}
}
void GetTemperature();
void GetHumidity();
void GetPressure();
void MeasurementsChanged()
{
NotifiyObserver();
}
void SetMeasurements(float temperature, float humidity, float pressure)
{
this->temperature = temperature;
this->humidity = humidity;
this->pressure = pressure;
MeasurementsChanged();
}
};
class CurrentConditionsDisplay : public Observer, public DisplayElement
{
private:
WeatherDate *p_weather_data;
float temperature;
float humidity;
float pressure;
public:
CurrentConditionsDisplay(WeatherDate *p_weather_data)
{
this->p_weather_data = p_weather_data;
//订阅
this->p_weather_data->RegisterObserver(this);
}
~CurrentConditionsDisplay()
{
//取消订阅
this->p_weather_data->RemoveObserver(this);
}
void update(float temperature, float humidity, float pressure)
{
this->temperature = temperature;
this->humidity = humidity;
this->pressure = pressure;
display();
}
void display()
{
printf("CurrentConditionsDisplay -> temperature:%.2f, humidity:%.2f, pressure:%.2f \n", temperature, humidity, pressure);
}
};
class StatisticsDisplay : public Observer, public DisplayElement
{
private:
WeatherDate *p_weather_data;
float temperature;
float humidity;
float pressure;
public:
StatisticsDisplay(WeatherDate *p_weather_data)
{
this->p_weather_data = p_weather_data;
//订阅
this->p_weather_data->RegisterObserver(this);
}
~StatisticsDisplay()
{
//取消订阅
this->p_weather_data->RemoveObserver(this);
}
void update(float temperature, float humidity, float pressure)
{
this->temperature = temperature;
this->humidity = humidity;
this->pressure = pressure;
display();
}
void display()
{
printf("StatisticsDisplay -> temperature:%.2f, humidity:%.2f, pressure:%.2f \n", temperature, humidity, pressure);
}
};
int main()
{
WeatherDate *p_weather_data = new WeatherDate();
CurrentConditionsDisplay *p_current_display = new CurrentConditionsDisplay(p_weather_data);
StatisticsDisplay *p_statistics_display = new StatisticsDisplay(p_weather_data);
p_weather_data->SetMeasurements(80, 65, 30.4f);
p_weather_data->SetMeasurements(81, 72, 32.4f);
p_current_display->~CurrentConditionsDisplay();//取消订阅
p_weather_data->SetMeasurements(79.5, 68, 34.2f);
return 0;
}