深入浅出设计模式二——WeatherData设计(观察者模式)实现一
?
UML详细图

良好的OO设计必须具备可复用、可扩展、可维护三个特性。
观察者模式:
?????? 出版者+订阅者=观察者模式
???????条件:订阅者向出版者订阅报纸; 出版者一旦有新报纸或有更新的报纸,就会给订阅者送达; 当订阅者不想再看报纸的时候,可取消订阅,这样出版者不再向取消订阅者送报纸; 只要报社还在运营,就会有人向他们订阅报纸。
?????? 这里将出版者抽象为Subject(主题),将订阅者抽象为observer(观察者)
????????????????
类似的求职者与猎头也可以这样抽象。如多个求职者打电话给猎头;猎头把他们加入求职列表之中,一旦有对应的职位就打电话通知相应的求职者;求职者也可以自己出去找工作,找到工作打电话告诉猎头不需要它帮助了,猎头把该求职者从求职列表中删除。
?
观察者模式的定义:
?????? 观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
观察者提供了一种对象设计,让主题和观察者之间松耦合。
在观察者模式中,主题与观察者之间是松耦合关系,增加观察者可删除观察者主题的代码不用修改,主题不会受任何影响。
设计原则四:为了交互对象之间的松耦合设计而努力。
实例一:天气预报,系统通过WeatherData获取观测到的数据,可能有多个布告板用来显示天气数据。当天气数据改变时要求实时更新布告板中的显示。要求程序员可以利用此API增加、删除自己的布告板及显示的内容。
此例符合观察者模式的要求。
天气预报系统的观察者模式图如下:

实现代码如下:
package com.lwf.disign.learn.observer.weatherdata;public interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObserver();}?
?
package com.lwf.disign.learn.observer.weatherdata;public interface Observer {void update();}?
?
package com.lwf.disign.learn.observer.weatherdata;import java.util.ArrayList;public class WeatherData implements Subject{ArrayList observerList;private float temperature;private float humidity;private float pressure;public WeatherData(){observerList = new ArrayList();}public void notifyObserver() {for(int i=0;i<observerList.size();i++){Observer o = (Observer)observerList.get(i);o.update();}}public void registerObserver(Observer o) {observerList.add(o);}public void removeObserver(Observer o) {int i = observerList.indexOf(o);if(i>=0){observerList.remove(o);}}public float getTemprature(){return temperature;}public float getHumidity(){return humidity;}public float getPressure(){return pressure;}public void measurementsChanged(){notifyObserver();}public void setMeasurements(float temperature,float humidity,float pressure){this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;measurementsChanged();}}?
?
package com.lwf.disign.learn.observer.weatherdata;public class CurrentConditionsDisplay implements Observer, DisplayElement {WeatherData weatherData;private float temperature;private float humidity;private float pressure;public CurrentConditionsDisplay(WeatherData weatherData){this.weatherData = weatherData;weatherData.registerObserver(this);}public void update() {this.temperature = weatherData.getTemprature();this.humidity = weatherData.getHumidity();this.pressure = weatherData.getPressure();this.display();}public void display() {System.out.println("Temperature:" + temperature + " Humidity:"+ humidity + " Pressure:" + pressure);}}?
?
package com.lwf.disign.learn.observer.weatherdata;public interface DisplayElement {void display();}?
?
下面是测试类:
package com.lwf.disign.learn.observer.weatherdata;public class WeatherDataTest {public static void main(String[] args) {WeatherData weatherData = new WeatherData();CurrentConditionsDisplay o1 = new CurrentConditionsDisplay(weatherData);CurrentConditionsDisplay o2 = new CurrentConditionsDisplay(weatherData);weatherData.setMeasurements(12, 23, 24);weatherData.setMeasurements(45, 55, 77);weatherData.removeObserver(o1);weatherData.setMeasurements(13, 23, 24);}}?
?
输出结果:
Temperature:12.0 Humidity:23.0 Pressure:24.0Temperature:12.0 Humidity:23.0 Pressure:24.0Temperature:45.0 Humidity:55.0 Pressure:77.0Temperature:45.0 Humidity:55.0 Pressure:77.0Temperature:13.0 Humidity:23.0 Pressure:24.0
?
上面实例源代码见附件:weatherdataSrc1.rar