设计模式之观察者模式
来源:互联网 发布:mac文件打包 编辑:程序博客网 时间:2024/05/22 15:23
某公司有一个气象站应用,有温度、湿度、气压感应装置,我们要做的是实现WeatherData对象,它可以从气象站获得数据并显示,显示方式有三种,对应三种布告板。
首先是一个错误示范:
public class BadWeatherData {//实例变量声明public void measurementsChanged(){float temp=getTemperature();float humidity=getHumidity();float pressure=getPressure();currentConditionsDisplay.update(temp,humidity,pressure);statisticsDisplay.update(temp,humidity,pressure);forecastDisplay.update(temp,humidity,pressure);}//其他方法}
update(temp,humidity,pressure)可以是一个统一的接口,而且针对具体实现编程,会导致我们以后再增加或删除布告板时必须修改程序。改变的地方,需要封装起来。
所以,here comes the observer pattern.观察者模式=出版者(subject)+订阅者(observer)。
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会收到通知并自动更新。
它提供了一种对象设计,让主题和观察者之间松耦合。
下面实现气象站:
public interface Subject {public void registerObserver(Observer o);public void removeObserver(Observer o);public void notifyObserver();}
public interface Observer {public void update(float temp,float humidity,float pressure);}
public interface DisplayElement {public void display();}
在WeatherData中实现subject接口:
import java.util.ArrayList;public class WeatherData implements Subject{private ArrayList observers;private float temperature;private float humidity;private float pressure;public WeatherData(){observers=new ArrayList<>();}@Overridepublic void registerObserver(Observer o) {// TODO Auto-generated method stubobservers.add(o);}@Overridepublic void removeObserver(Observer o) {// TODO Auto-generated method stubint i=observers.indexOf(o);observers.remove(i);}@Overridepublic void notifyObserver() {// TODO Auto-generated method stubfor(int i=0;i<observers.size();i++){Observer observer=(Observer)observers.get(i);observer.update(temperature, humidity, pressure);}}public void measurementsChanged(){notifyObserver();}public void setMeasurements(float temperature,float humidity,float pressure){this.temperature=temperature;this.humidity=humidity;this.pressure=pressure;measurementsChanged();}//其他方法}
建立布告板:
public class CurrentConditionsDisplay implements Observer,DisplayElement{private float temperature;private float humidity;private Subject weatherData;public CurrentConditionsDisplay(Subject weatherData){this.weatherData=weatherData;weatherData.registerObserver(this);}@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("Current conditions:"+temperature+"F degrees and"+humidity+"% humidity");}@Overridepublic void update(float temp, float humidity, float pressure) {// TODO Auto-generated method stubthis.temperature=temp;this.humidity=humidity;display();}}
public class ForecastDisplay implements Observer,DisplayElement{private float temperature;private float humidity;private float pressure;private Subject weatherData;public ForecastDisplay(Subject weatherData){this.temperature=temperature;this.humidity=humidity;this.pressure=pressure;weatherData.registerObserver(this);}@Overridepublic void display() {// TODO Auto-generated method stubif(temperature>80&&humidity>65&&pressure<29.5f)System.out.println("Improving weather on the way");else if(temperature<70&&pressure>30f)System.out.println("Watch out for cooler,rainy weather");else System.out.println("More of the same");}@Overridepublic void update(float temp, float humidity, float pressure) {// TODO Auto-generated method stubthis.temperature=temp;this.humidity=humidity;this.pressure=pressure;display();}}
public class StatisticsDisplay implements Observer,DisplayElement{private float pressure;private Subject weatherData;public StatisticsDisplay(Subject weatherData){this.weatherData=weatherData;weatherData.registerObserver(this);}@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("Pressure is "+pressure);}@Overridepublic void update(float temp, float humidity, float pressure) {// TODO Auto-generated method stubthis.pressure=pressure;display();}}
public class WeatherStation {public static void main(String[]args){WeatherData weatherData=new WeatherData();CurrentConditionsDisplay currentConditionsDisplay=new CurrentConditionsDisplay(weatherData);StatisticsDisplay statisticsDisplay=new StatisticsDisplay(weatherData);ForecastDisplay forecastDisplay=new ForecastDisplay(weatherData);weatherData.setMeasurements(90,70,29f);weatherData.setMeasurements(65, 75, 31f);weatherData.setMeasurements(70, 75, 30f);}}
运行程序:
Current conditions:90.0F degrees and70.0% humidityPressure is 29.0Improving weather on the wayCurrent conditions:65.0F degrees and75.0% humidityPressure is 31.0Watch out for cooler,rainy weatherCurrent conditions:70.0F degrees and75.0% humidityPressure is 30.0More of the same
使用Java内置的观察者模式:
java.util包内包含最基本的Observer接口和Observable类。
和以上的实现类似,但有差异,WeatherData现在扩展自Observable类,并继承到一些增加删除通知Observer的方法。
重做气象站:
import java.util.Observable;public class WeatherData extends Observable{private float temperature;private float humidity;private float pressure;public WeatherData(){}public void measurementsChanged(){setChanged();notifyObservers();}public void setMeasurements(float temperature,float humidity,float pressure){this.temperature=temperature;this.humidity=humidity;this.pressure=pressure;measurementsChanged();}public float getTemperature(){return temperature;}public float getHumidity(){return humidity;}public float getPressure(){return pressure;}}
布告栏:
import java.util.Observable;import java.util.Observer;public class CurrentConditionsDisplay implements Observer,DisplayElement{Observable observable;private float temperature;private float humidity;public CurrentConditionsDisplay(Observable observable){this.observable=observable;observable.addObserver(this);}@Overridepublic void display() {// TODO Auto-generated method stubSystem.out.println("Current conditions:"+temperature+"F degrees and"+humidity+"% humidity");}@Overridepublic void update(Observable o, Object arg) {// TODO Auto-generated method stubif(o instanceof WeatherData){WeatherData weatherData=(WeatherData)o;this.temperature=weatherData.getTemperature();this.humidity=weatherData.getHumidity();display();}}}
etc
运行代码:
Improving weather on the wayPressure is 29.0Current conditions:90.0F degrees and70.0% humidityWatch out for cooler,rainy weatherPressure is 31.0Current conditions:65.0F degrees and75.0% humidityMore of the samePressure is 30.0Current conditions:70.0F degrees and75.0% humidity
仔细看会发现输出的次序不一样了。如果我们依赖次序,这样就错了。
所以,java.util.Observable也有局限性,它是一个类不是接口,限制了它的使用和复用。
ps,其实JavaBeans和Swing中,也实现了观察者模式。
0 0
- 设计模式之-观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- poj 3335 && poj 3130 && poj 2451 && poj 1474(n(logn)求解半平面交)
- nxoj系统的第一题:a+b问题
- 2014年百度软件研发实习生电面总结
- [codility]MinAvgTwoSlice
- Android无法更新R文件
- 设计模式之观察者模式
- 算法基础_数字数码管
- Spring HttpInvoker源码分析
- 微信行政助手班车LBS智能查询
- 堆—数据结构
- android使用篇(四) 注解依赖注入IOC实现绑定控件
- HDOJ 1525 Euclid's Game 博弈论
- c#写xml文件
- 最强生活信息导航:“广州沃妹”微信LBS功能体验