设计模式——theObserverPattern(观察者模式)KeepingyouObjectintheknow2007年12月2007-11-02内容大纲问题示例定义实际应用相关模式2007-11-02问题内容开发一个天气监控系统,将从气象台取得的数据,在终端上显示出来。要求当气象台数据变化时,即时在显示界面上更新,并保证显示内容的可扩展性。气温气压湿度气象台已有的需要开发的取天气数据显示WeatherData对象2007-11-02气象台提供的部分源码+getHumidity()+getPressure()+getTemperature()+measurementsChanged()WeatherData三个取得最近天气新状况的方法,在气象数据变化时,相应的值会被修改成最新的,我们不需要关心是如何改变的。当天气数据发生变化时,自动调用该方法,我们通过修改此方法代码,调用显示终端提供的方法,以更新显示数据。目前要实现三种显示内容:1、当前天气数据2、气温详情3、天气预报2007-11-02最EZ的实现方法publicclassWeatherData{//三种显示内容处理类privateConditionsDisplaycurrentConditionsDisplay;privateStatistatcsDisplaystatistatcsDisplay;privatePorecastDisplayforecastDisplay;publicvoidmeasurementsChanged(){floattemp=getTemperature();floathumidity=getHumidity();floatpressure=getPressure();currentConditionsDisplay.update(temp,humidity,pressure);statistatcsDisplay.update(temp,humidity,pressure);forecastDisplay.update(temp,humidity,pressure);}//其它方法。。。}搞定对具体类编码,如果不修改码,就无法增加删除其它显示内容应该用一个有update方法的接口变化的部分应该封装起来。2007-11-02报刊订阅报纸有的是,来订阅吧。邮递员报社我要看报订报读者2007-11-02取消订阅都是广告!我不看了!爱看不看!报社取消订阅读者观察者Observer被观察者Subject2007-11-02观察者模式定义观察者模式属于行为模式,是定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。2007-11-02观察者模式类图+registerObserver()+removerObserver()+notifyObersvers()+getTemperature()+setHumidity()+getPressure()+measurementsChanged()ConcreteSubject+update()ConcreteObserverobserverssubject+registerObserver()+removerObserver()+notifyObersvers()interfaceSubject+update()interfaceObserver2007-11-02天气监控系统设计registerObserver()removerObserver()notifyObersvers()interfaceSubjectregisterObserver()removerObserver()notifyObersvers()getTemperature()setHumidity()getPressure()measurementsChanged()WeatherDataupdate()display()CurrentConditionsDisplayobserverssubject+display()interfaceDisplayElement+display()+update()StatisticsDisplay+update()interfaceObserver+display()+update()ForecastDisplay+display()+update()OtherDisplay2007-11-02Subject实现publicclassWeatherDataimplementsSubject{privateArrayListobservers;privatefloattemperature;privatefloathumidity;privatefloatpressure;publicWeatherData(){observers=newArrayList();}publicvoidregisterObserver(Observero){observers.add(o);}2007-11-02Subject实现(续)publicvoidremoveObserver(Observero){inti=observers.indexOf(o);if(i=0){observers.remove(o);}}publicvoidnotifyObservers(){for(inti=0;iobservers.size();i++){Observerobserver=(Observer)observers.get(i);observer.update(temperature,humidity,pressure);}}publicvoidmeasurementsChanged(){notifyObservers();}//………………othermethod}2007-11-02Observer实现publicclassCurrentConditionsDisplayimplementsObserver,DisplayElement{privatefloattemperature;privatefloathumidity;fprivateSubjectweatherData;publicCurrentConditionsDisplay(SubjectweatherData){this.weatherData=weatherData;weatherData.registerObserver(this);}publicvoidupdate(floattemp,floathumidity,floatpressure){this.temperature=temp;this.humidity=humidity;display();}publicvoiddisplay(){/*...*/}}2007-11-02完成喽•通过使用Observer模式,完成了数据变化与显示系统的联动。•实现了“降低耦合”的面向对像的设计原则。•当增加显示种类时,只需开发相应的Observer端,并在运行时注册即可。•可在运行期内修改注册关系,以决定是否随Subject数据变化而变化显示状态。2007-11-02PullvsPush两种方式的优劣?2007-11-02推vs拉•推方式的特点:–当状态发生变化时,一次性将所有数据数据推给观察者。–不向观察者开放内部数据接口–只要是观察者被注册,观察者将始终收到数据。•拉方式的特点:–观察者可根据需要取Subject提供的数据。–Subject必须提供取数据接口(getter)–观察者可按自己的要求决定是否接收数据。2007-11-02Java内置的Observer模式•在java.util包中,包含了最基本的Observer接口和Observable类,为在Java中使用Observer模式提供了方便。•Java内置的Observer与我们前面介绍的很类似,只是已经实现了很多基本的功能,如注册和通知观察者等。•可以支持用推或者拉的方式,向观察者传送数据,使用更灵活。2007-11-02Java内置的Observer•java.util.Observable不是一个接口,而是一个类,实现了增、删以及通知Observer的方法,Subject只需继承该类,当状态改变时,调用通知即可。•通知观察者时,需要覆盖notifyObservers()方法。无参数时,需要观察者自己拉数据。否则,调用notifyObservers(Object)方法将一个参数对象传给观察者。•Java.util.Observer是接口,观察者类实现该接口,主要是update(obs,arg)方法,并实现自有功能。2007-11-02使用Java内内置的Observer+addObserver()+deleteObserver()+notifyObservers()+setChanged()Observableextends+getTemperature()+getHumidity()+getPressure()+measurementsChanged()WeatherData+update()+display()ConditionsDisplay+update()interfaceObserver+display()+update()ForecastDisplay+display()+update()StatisticsDisplayobserverssubject2007-11-02SetChanged()?privatebooleanchanged=false;voidsetChanged(){changed=true;}voidnotifyObservers(Objectarg){if(changed){for(;;){//...}changed=false;}}作用:提高灵活性,使得编程人员可以根据附加的条件选择是否通知观察者。使用Java内置的Observer2007-11-02publicclassWeatherDataextendsObservable{privatefloattemperature,humidity,pressure;publicWeatherData(){}publicvoidmeasurementsChanged(){setChanged();notifyObservers();}publicvoidsetMeasurements(floattemperature,floathumidity,floatpressure){this.temperature=temperature;this.humidity=humidity;this.pressure=pressure;measurementsChanged();}publicfloatgetTemperature(){...}publicfloatgetHumidity(){...}publicfloatgetPressure(){...}}Observer实现2007-11-02publicclassCurrentConditionsDisplayimplementsObserver{Observableobservable;privatefloattemperature,humidity;publicCurrentConditionsDisplay(Observableobservable){this.observable=observable;observable.addObserver(this);}publicvoidupdate(Observableobs,Objectarg){if(obsinstanceofWeatherData){WeatherDataweatherData=(WeatherDat