深入浅出设计模式-002:观察者模式(Observer Pattern)
一:观察者模式 = 出版者(主题Subject)+订阅者(观察者Observer) 定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖都会收到通知并自动更新。 主题和观察者定义了一对多关系。观察者依赖此主题,只要主题状态一有变化,观察者就会被通知。
二:松耦合的威力:当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。 设计原则:为了交互对象之间的松耦合设计而努力。
Subject:这是主题接口,对象使用此接口注册为观察者,或者把自己从观察者中删除。 Observer:所有潜在的观察者必须实现观察者接口,这个接口只有UPDATE一个方法,当主题改变它时被调用。 ConcreteSubject:实现主题接口,还用于在状态改变时更新所有当前观察者。 ConcreteObserver:具体观察者可以是实现此接口的任意类。观察者必须注册具体主题,以便接口更新。
三:观察者定义了对象之间一对多的关系 主题用一个共同的接口来更新观察者 观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者的接口。 使用此模式时,你可从被观察者出推或拉数据 有多个观察者时,不可以依赖特定的通知次序 四:类似于,在网上公布电话,订阅者想订阅时,可以通过电话通知。 public interface Observer{ //当气象观测值改变时,主题会把这些状态值当做方法的参数,传递给观察者 void update(float tmp, float humidity, float pressure); } public interface DisplayElement{ //当布告需要显示时,调用此方法 void display(); } public class CurrentDistionsDisplay : Observer, DisplayElement{ private float temperature; private float humidity; private Subject weatherData; public CurrentDistionsDisplay(Subject weatherData){ //注册用 this.weatherData = weatherData; weatherData.registerObserver(this); } public void update(float tmp, float humidity, float pressure){ temperature = tmp; this.humidity = humidity; display(); } public void display(){ Console.WriteLine("CurrentDistionsDisplay"); } } public class StatisticsDisplay : Observer, DisplayElement{ private float temperature; private float humidity; private Subject weatherData; public StatisticsDisplay(Subject weatherData){ this.weatherData = weatherData; weatherData.registerObserver(this); } public void update(float tmp, float humidity, float pressure){ temperature = tmp; this.humidity = humidity; display(); } public void display(){ Console.WriteLine("StatisticsDisplay"); } } public class ForecastDisplay : Observer, DisplayElement{ private float temperature; private float humidity; private Subject weatherData; public ForecastDisplay(Subject weatherData){ this.weatherData = weatherData; weatherData.registerObserver(this); } public void update(float tmp, float humidity, float pressure){ temperature = tmp; this.humidity = humidity; display(); } public void display(){ Console.WriteLine("ForecastDisplay"); } } public interface Subject{ //该观察者用来注册或被删除的 void registerObserver(Observer o); void removeObserver(Observer o); //当主题状态改变时,这个方法会被调用,以通知所有的观察者 void notifyObservers(); } public class WeatherData : 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 index = observers.IndexOf(o); if(index >= 0) observers.Remove(index); } public void notifyObservers(){ for (int index = 0; index < observers.Count; index++){ Observer observer = (Observer)observers[index]; observer.update(temperature, humidity, pressure); } } public void measurementsChanged(){ notifyObservers(); } public void setMeasurements(float temp, float humi, float press){ temperature = temp; humidity = humi; pressure = press; measurementsChanged(); } }
static void Main(string[] args){ WeatherData weatherData = new WeatherData(); CurrentDistionsDisplay currentDisplay = new CurrentDistionsDisplay(weatherData); StatisticsDisplay statistics = new StatisticsDisplay(weatherData); ForecastDisplay forecast = new ForecastDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30); weatherData.setMeasurements(82, 70, 29); }