假定我们需要为Weather-O-Rama公司建立一个气象站系统,除已有的WeatherData有数据源类,还需要更新三个布告板的显示:目前状况(温度、湿度、气压)、气象统计和天气预报。

1 以下是一个可能的实现
class WeatherData
{
private:
	//实例变量声明
public:
	void measurementsChanged()
	{
		float temp = getTemperature();
		float humidity = getHumidity();
		float pressure = getPressure();
		currentConditionsDisplay.update(temp, humidity, pressure);
		statisticsDisplay.update(temp, humidity, pressure);
		forecastDisplay.update(temp, humidity, pressure);
	}
	float getTemperature() {}
	float getHumidity() {}
	float getPressure() {}
};上述实现有以下问题存在:
- 针对具体实现编程,而非针对接口(currentConditionsDisplay都是具体的实例)
- 针对每个新的布告板,都得修改代码(添加新的布告板到代码中)
- 无法在运行时动态增删布告板
- 尚未封装改变的部分(调用几个update的地方)
2 观察者模式
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

主题是具有状态的对象,并且可以控制这些状态。另一方面,观察者使用这些状态,虽然这些状态不属于他们。
观察者模式提供了一种对象设计(设计原则:为了交互对象之间的松耦合设计而努力),让主题和观察者之间松耦合。
主题只知道观察者实现了某个接口,并不需要知道具体的观察者是谁,做了什么动作。同时,我们也可以在运行时增删观察者。

class Subject
{
public:
	virtual void registerObserver(Observer o) = 0;
	virtual void removeObserver(Observer o) = 0;
	virtual void notifyObserver() = 0;
};
class Observer
{
public:
	virtual void update(float temp, float humidity, float pressure) = 0;
};
class DisplayElement
{
public:
	virtual void display() = 0;
};// WeatherData实现接口
class WeatherData : public Subject
{
private:
	std::vector<Observer*> observers;
	float temprature;
	float humidity;
	float pressure;
public:
	WeatherData()
	{
		observers = new vector<Observer*>();
	}
	void registerObserver(Observer* o)
	{
		observers.add(o);
	}
	void removeObserver(Observer* o)
	{
		observers.remove(o);
	}
	void notifyObserver()
	{
		for (Observer* o : observers)
		{
			o->update(temprature, humidity, pressure);
		}
	}
	void measurementsChanged()
	{
		notifyObserver();
	}
};// 布告板实现Observer接口
// 为什么要保存对Subject的引用呢,构造完后好像并未使用?
// 以后可能想要取消注册,如果有对Subject的引用会比较方便。
class CurrentConditionsDisplay : public Observer, DisplayElement
{
private:
	Subject* weatherData;
	float temprature;
	float humidity;
public:
	CurrentConditionsDisplay(Subject* weatherData)
	{
		this->weatherData = weatherData;
		weatherData->registerObserver(this);
	}
	void update(float temp, float humidity, float pressure)
	{
		this->temprature = temp;
		this->humidity = humidity;
		display();
	}
	void display()
	{
		std::cout << "Temprature:" << temprature << "Humidity:" << humidity << std::endl;
	}
};除使用上面的“推”方式主动将数据传送给观察者,还可以通过“拉”方式主动拉取数据(可以传递一个主题对象,或者数据对象给update方法,或者从私有变量中提取)。
// 主题本身作为变量,可以让观察者知道是哪个主题通知的
update(Observer o) {}
// Java的内置实现有setChanged()方法,可以在更新观察者时具有更多的弹性,比如什么时候可以
// 不更新,什么时候更新


















