观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。观察者依赖于此主题,只要主题状态一有变化,观察者就会被通知,根据通知的风格,观察者可能因此新值而更新。关于观察者的一切,主题只知道观察者实现了某个接口,主题不需要知道观察者的具体类是谁、做了些什么工作或其他任何细节。任何时候我们都可以增加新的观察者,因为主题唯一依赖的东西是一个实现Observer接口的对象列表,所以我们可以随时增加观察者。假如我们有个新的具体类需要当观察者,不需要为了兼容新类型而修改主题代码,所有要做的就是在新的类里实现此观察者接口,然后注册为观察者即可。主题不在乎别的,它只发送通知给所有实现了观察者接口的对象。
#include"subject.h"
int main()
{
WeatherData *weatherData = new WeatherData();
CurrentConditionDisplay *currentDisplay = new CurrentConditionDisplay(weatherData);
StatisticsDisplay *statisticsDisplay = new StatisticsDisplay(weatherData);
ForecastDisplay *forecastDisplay = new ForecastDisplay(weatherData);
weatherData->setMeasurements(80, 65, 30.4);
weatherData->setMeasurements(82, 70, 29.2);
weatherData->setMeasurements(78, 90, 29.2);
delete weatherData;
delete currentDisplay;
delete statisticsDisplay;
delete forecastDisplay;
}
#ifndef __SUBJECT_H
#define __SUBJECT_H
#include<vector>
#include<iostream>
using namespace std;
class Observer
{
public:
virtual void update(float temp, float humidity, float pressure) = 0;
virtual void display()=0;
};
class Subject
{
public:
virtual void registerObserver(Observer *O) = 0;
virtual void removeObserver(Observer *O) = 0;
virtual void notifyObservers() = 0;
};
class WeatherData :public Subject
{
private:
vector<Observer*> observers;
float temperature;
float humidity;
float pressure;
public:
WeatherData(){}
void registerObserver(Observer *o)
{
observers.push_back(o);
}
void removeObserver(Observer *o)
{
}
void notifyObservers()
{
for (int i = 0; i < observers.size(); ++i)
{
observers[i]->update(temperature, humidity, pressure);
}
}
void measurementsChanged()
{
notifyObservers();
}
void setMeasurements(float temperature, float humidity, float pressure)
{
this->temperature = temperature;
this->humidity = humidity;
this->pressure = pressure;
measurementsChanged();
}
};
class CurrentConditionDisplay :public Observer
{
private:
float temperature;
float humidity;
Subject *weatherData;
public:
CurrentConditionDisplay(Subject* weatherData) :weatherData(weatherData)
{
weatherData->registerObserver(this);
}
void update(float temperature, float humidity, float pressure)
{
this->temperature = temperature;
this->humidity = humidity;
display();
}
void display()
{
cout << "Current conditions: " << temperature << "F degrees and " << humidity << "% humidity" << endl;
}
};
class StatisticsDisplay :public Observer
{
private:
float maxTemp;
float minTemp;
float tempSum;
int numReadings;
Subject *weatherData;
public:
StatisticsDisplay(Subject *weatherData) :weatherData(weatherData), maxTemp(0.0), minTemp(200.0), tempSum(0.0)
{
weatherData->registerObserver(this);
}
void update(float temp, float humidity, float pressure)
{
tempSum += temp;
numReadings++;
if (temp > maxTemp)
{
maxTemp = temp;
}
if (temp < minTemp)
{
minTemp = temp;
}
display();
}
void display()
{
cout << "Avg/Max/Min temperature = " << (tempSum / numReadings) << "/" << maxTemp << "/" << minTemp << endl;
}
};
class ForecastDisplay :public Observer
{
private:
float currentPressure;
float lastPressure;
Subject *weatherData;
public:
ForecastDisplay(Subject *weather) :weatherData(weather), currentPressure(29.92), lastPressure(0.0)
{
weatherData->registerObserver(this);
}
void update(float temp, float humidity, float pressure)
{
lastPressure = currentPressure;
currentPressure = pressure;
display();
}
void display()
{
cout << "Forecast: ";
if (currentPressure > lastPressure)
cout << "Improving weather on the way" << endl;
else if (currentPressure == lastPressure)
cout << "More of the same" << endl;
else
cout << "Watch out for cooler, rainy weather" << endl;
}
};
#endif