观察者模式(Observer Pattern):定义了对象之间的一对多依赖,这样一样,当一个对象(主题)改变状态时,它的所有依赖者(观察者)都会收到通知并自动更新
注:可以使用推或拉的方法,推(主题自动更新数据),拉(观察者主动更新数据,例如使用getter方法)
实例:气象站要实时通知布告板更新数据,布告板应该能灵活地增加
分析:如果在气象站里直接接加布告板则违反了针对接口编程的原则,无法动态地增加布告板.
代码:
JAVA:
- import java.util.ArrayList;
- interface Observer
- {
- public void update(float temp, float humidity, float pressure);
- }
- interface Subject
- {
- public void registerObserver(Observer o);
- public void removeObserver(Observer o);
- public void notifyObservers();
- }
- interface DisplayElement
- {
- public void display();
- }
- class WeatherData implements Subject
- {
- private ArrayList observers;
- private float temperature;
- private float humidity;
- private float pressure;
- public WeatherData()
- {
- observers = new ArrayList();
- }
- public void registerObserver(Observer o)
- {
- observers.add(o);
- }
- public void removeObserver(Observer o)
- {
- int i = observers.indexOf(o);
- if (i >= 0)
- {
- observers.remove(i);
- }
- }
- public void notifyObservers()
- {
- for (int i = 0; i < observers.size(); i++)
- {
- Observer observer = (Observer)observers.get(i);
- observer.update(temperature, humidity, pressure);
- }
- }
- public void measurementsChanged()
- {
- notifyObservers();
- }
- public void setMeasurements(float temperature, float humidity, float pressure)
- {
- this.temperature = temperature;
- this.humidity = humidity;
- this.pressure = pressure;
- measurementsChanged();
- }
- }
- class CurrentConditionsDisplay implements Observer, DisplayElement
- {
- private float temperature;
- private float humidity;
- private Subject weatherData;
- public CurrentConditionsDisplay(Subject weatherData)
- {
- this.weatherData = weatherData;
- weatherData.registerObserver(this);
- }
- public void update(float temperature, float humidity, float pressure)
- {
- this.temperature = temperature;
- this.humidity = humidity;
- display();
- }
- public void display()
- {
- System.out.println("Current condition :" + temperature + "F degrees and " + humidity + "% humidity");
- }
- }
- class ForecastDisplay implements Observer, DisplayElement
- {
- private float currentPressure = 29.92f;
- private float lastPressure;
- private Subject weatherData;
- public ForecastDisplay(Subject weatherData)
- {
- this.weatherData = weatherData;
- weatherData.registerObserver(this);
- }
- public void update(float temperature, float humidity, float pressure)
- {
- lastPressure = currentPressure;
- currentPressure = temperature;
- display();
- }
- public void display()
- {
- System.out.print("Forecast: ");
- if (currentPressure > lastPressure)
- {
- System.out.println("Improving weather on the way!");
- }
- else if (currentPressure == lastPressure)
- {
- System.out.println("More of the same");
- }
- else if (currentPressure < lastPressure)
- {
- System.out.println("Watch out for cooler, rainy weather");
- }
- }
- }
- class StatisticsDisplay implements Observer, DisplayElement
- {
- private float maxTemp = 0.0f;
- private float minTemp = 200;
- private float tempSum = 0.0f;
- private int numReadings;
- private Subject weatherData;
- public StatisticsDisplay(Subject weatherData)
- {
- this.weatherData = weatherData;
- weatherData.registerObserver(this);
- }
- public void update(float temperature, float humidity, float pressure)
- {
- tempSum += temperature;
- numReadings++;
- if (temperature > maxTemp)
- {
- maxTemp = temperature;
- }
- if (temperature < minTemp)
- {
- minTemp = temperature;
- }
- display();
- }
- public void display()
- {
- System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)
- + "/" + maxTemp + "/" + minTemp);
- }
- }
- public class WeatherStation
- {
- public static void main(String[] args)
- {
- WeatherData weatherData = new WeatherData();
- Observer currentDisplay = new CurrentConditionsDisplay(weatherData);
- Observer forecastDisplay = new ForecastDisplay(weatherData);
- Observer statisticsDisplay = new StatisticsDisplay(weatherData);
- weatherData.setMeasurements(80, 65, 30.4f);
- weatherData.setMeasurements(82, 70, 29.2f);
- weatherData.removeObserver(forecastDisplay);
- weatherData.setMeasurements(78, 90, 29.2f);
- }
- }
C++:
- // WeatherStation.cpp : 定义控制台应用程序的入口点。
- //
- #include "stdafx.h"
- #include <iostream>
- #include <list>
- using namespace std;
- class Observer
- {
- public:
- virtual void update(float temp, float humidity, float pressure)=0;
- };
- class Subject
- {
- public:
- virtual void registerObserver(Observer* o)=0;
- virtual void removeObserver(Observer* o)=0;
- virtual void notifyObservers()=0;
- };
- class DisplayElement
- {
- public:
- virtual void display()=0;
- };
- class WeatherData :public Subject
- {
- private:
- list<Observer *> observers;
- float temperature;
- float humidity;
- float pressure;
- public:
- WeatherData()
- {
- }
- void registerObserver(Observer* o)
- {
- observers.push_back(o);
- }
- void removeObserver(Observer* o)
- {
- observers.remove(o);
- }
- void notifyObservers()
- {
- list<Observer *>::iterator iter;
- for(iter=observers.begin();iter!=observers.end();iter++)
- {
- (*iter)->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 CurrentConditionsDisplay :public Observer, public DisplayElement
- {
- private:
- float temperature;
- float humidity;
- Subject* weatherData;
- public:
- CurrentConditionsDisplay(Subject* weatherData)
- {
- this->weatherData = weatherData;
- weatherData->registerObserver(this);
- }
- void update(float temperature, float humidity, float pressure)
- {
- this->temperature = temperature;
- this->humidity = humidity;
- display();
- }
- void display()
- {
- cout<<"Current condition :" << temperature << "F degrees and " << humidity << "% humidity/n";
- }
- };
- class ForecastDisplay :public Observer, public DisplayElement
- {
- private:
- float currentPressure;
- float lastPressure;
- Subject* weatherData;
- public:
- ForecastDisplay(Subject* weatherData)
- {
- currentPressure = 29.92f;
- this->weatherData = weatherData;
- weatherData->registerObserver(this);
- }
- void update(float temperature, float humidity, float pressure)
- {
- lastPressure = currentPressure;
- currentPressure = temperature;
- display();
- }
- void display()
- {
- cout<<"Forecast: ";
- if (currentPressure > lastPressure)
- {
- cout<<"Improving weather on the way!/n";
- }
- else if (currentPressure == lastPressure)
- {
- cout<<"More of the same/n";
- }
- else if (currentPressure < lastPressure)
- {
- cout<<"Watch out for cooler, rainy weather/n";
- }
- }
- };
- class StatisticsDisplay:public Observer, public DisplayElement
- {
- private:
- float maxTemp ;
- float minTemp ;
- float tempSum ;
- int numReadings;
- Subject* weatherData;
- public:
- StatisticsDisplay(Subject* weatherData)
- {
- maxTemp = 0.0f;
- minTemp = 200;
- tempSum = 0.0f;
- this->weatherData = weatherData;
- weatherData->registerObserver(this);
- }
- void update(float temperature, float humidity, float pressure)
- {
- tempSum += temperature;
- numReadings++;
- if (temperature > maxTemp)
- {
- maxTemp = temperature;
- }
- if (temperature < minTemp)
- {
- minTemp = temperature;
- }
- display();
- }
- void display()
- {
- cout<<"Avg/Max/Min temperature = " << tempSum / numReadings<<"/" <<maxTemp << "/" << minTemp<<endl;
- }
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- WeatherData* weatherData = new WeatherData();
- Observer* currentDisplay = new CurrentConditionsDisplay(weatherData);
- Observer* forecastDisplay = new ForecastDisplay(weatherData);
- Observer* statisticsDisplay =new StatisticsDisplay(weatherData);
- weatherData->setMeasurements(80, 65, 30.4f);
- weatherData->setMeasurements(82, 70, 29.2f);
- weatherData->removeObserver(forecastDisplay);
- weatherData->setMeasurements(78, 90, 29.2f);
- return 0;
- }
结果: