标签:
第二节观察者模式(OberverPattern)
HeadFirst这节给出的案例是气象站监测应用系统。背景是:气象站通过物流装置获取气象信息,生成WeatherData(气象数据),最后通过布告板显示给用户。WeatherData可以获取物理装置的数据,并且将数据显示到布告板上:目前状况(温度、湿度、气压)、气象统计和天气预报。
先给出一个错误示范
public class WeatherData { public float GetTemperature() { return 25; } public float GetHumidity() { return 60; } public float GetPressure() { return 1; } public void MeasurementsChanged(){ float temp = GetTemperature(); float humidity = GetHumidity(); float pressure = GetPressure(); CurrentConditionsDisplay.Update(temp, humidity, pressure); StatisticsDisplay.Update(temp, humidity, pressure); ForecasDisplay.Update(temp, humidity, pressure); } }
这个代码示例中在更新布告板的时候,有两个问题:1、因为更新布告板都是调用了Update()方法,且参数都相同,这就违背了上一张策略模式中,需要将改变的地方封装起来。2、现在的布告板都是针对现实编程,如果要增加或删除布告板时就不要修改代码。
我们先不急于解决这些问题,先了解一下观察者模式(Observer)。
定义:观察者模式定义了对象之间一对多依赖,这样依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
对象通过主题接口注册为观察者或把自己从观察者中删除。一个具体的主题来实现主题接口。
利用观察者模式主题和观察者实现了之间的松耦合。使之直接可以交互,但是不清楚彼此的细节。
这里应用了一个设计原则--为交互对象之间的松耦合设计而努力
松耦合的设计之所以能让我们建立有弹性的OO系统,能够对应变化,是因为对象之间的互相依赖降到了最低。
回到气象站的问题,我们用观察者模式来设计气象站系统,如下图所示类图。
这样我们来实现这些代码
气象站的接口及实现类
public interface IWeatherData { /// <summary> /// 注册成为观察者 /// </summary> /// <param name="o"></param> void RegisterObserver(IObserver o); /// <summary> /// 取消观察者 /// </summary> /// <param name="o"></param> void RemoveObserver(IObserver o); /// <summary> /// 当数据更新是调用 /// </summary> void NotifyObserver(); }
public class WeatherData:IWeatherData { private ArrayList Observers; private float temperature; private float humidity; private float pressure; public WeatherData() { this.Observers = new ArrayList(); } public void RegisterObserver(IObserver o) { this.Observers.Add(o); } public void RemoveObserver(IObserver o) { this.Observers.Remove(o); } public void NotifyObserver() { foreach (IObserver item in Observers) { item.Update(this.temperature,this.humidity,this.pressure); } } public void MeasurementsChanged() { NotifyObserver(); } public void SetMeasurements(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; this.pressure = pressure; MeasurementsChanged(); } }
布告板的接口及实现类
public interface IObserver { void Update(float temp, float humidity, float pressure); } public interface IDisplayElement { void Display(); }
public class CurrentConditionsDisplay:IObserver,IDisplayElement { private float temperature; private float humidity; private float pressure; public IWeatherData weatherData; public CurrentConditionsDisplay(IWeatherData weatherData) { this.weatherData = weatherData; weatherData.RegisterObserver(this); } public void Update(float temp, float humidity, float pressure) { this.temperature = temp; this.humidity = humidity; this.pressure = pressure; Display(); } public void Display() { Console.WriteLine(string.Format("气压版显示 温度:{0},湿度:{1}",this.temperature,this.humidity)); } }
这样准备工作就做完了,开始执行
WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); weatherData.SetMeasurements(80, 65, 30.4f);
同理,我们再将其他的观察者同样处理,修改完成后,在执行语句里面添加定义即可
WeatherData weatherData = new WeatherData(); CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData); StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); weatherData.SetMeasurements(80, 65, 30.4f);
OK执行结果达到了需求。
通过学习我们知道,当我们后面再要添加新的观察者或者要去掉以前的观察者时,不需要对WeatherData进行任何编辑,只需要把观察者的接口进行实现,并且在调用的时候注册即可。这样系统就非常有弹性。
HeadFirst设计模式(2)-观察者模式(ObserverPattern)
标签:
原文地址:http://www.cnblogs.com/athens/p/4476405.html