观察者模式在气象站中的运用
源码地址:
https://github.com/BaronZ88/DesignPatterns/tree/master/src/com/baron/patterns/observer
观察者模式介绍:
观察者模式面向的需求是:A对象(观察者)对B对象(被观察者)的某种变化高度敏感,需要在B变化的一瞬间做出反应。程序里的观察者采用注册(Register)或者成为
订阅(Subscribe)的方式告诉被观察者:我需要你的某某状态,你要在它变化时通知我。采取这样被动的观察方式,既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。
气象站的WeatherData应用的介绍:
两个公告牌CurrentConditionDisplay和ForecDisplay实现了Observer和DisplayElem接口,在他们的构造方法中会调用WeatherData的registerObserver方法将自己注册成观察者,这样被观察者WeatherData就会持有观察者的应用,并将它们保存到一个集合中。当被观察者WeatherData状态发生变化时就会遍历整个集合,循环调用观察者公告牌更新数据的方法。后面如果我们需要增加或者删除公告牌就只需新增或者删除实现了Observer
和
DisplayElement`接口的公告牌就好了。 观察者模式将观察者和主题(被观察者)彻底解耦,主题只知道观察者实现了某一接口(也就是Observer接口)。并不需要观察者的具体类是谁、做了些什么或者其他任何细节。任何时候我们都可以增加新的观察者。因为主题唯一依赖的东西是一个实现了Observer接口的对象列表。
主题接口
1 /** 2 * 主题(发布者、被观察者) 3 */ 4 public interface Subject { 5 6 /** 7 * 注册观察者 8 */ 9 void registerObserver(Observer observer); 10 11 /** 12 * 移除观察者 13 */ 14 void removeObserver(Observer observer); 15 16 /** 17 * 通知观察者 18 */ 19 void notifyObservers(); 20 }
观察者接口
1 ** 2 * 观察者 3 */ 4 public interface Observer { 5 void update(); 6 }
公告牌用于显示的公共接口
1 public interface DisplayElement { 2 void display(); 3 }
WeatherData的实现
1 public class WeatherData implements Subject { 2 3 private List<Observer> observers; 4 5 private float temperature;//温度 6 private float humidity;//湿度 7 private float pressure;//气压 8 private List<Float> forecastTemperatures;//未来几天的温度 9 10 public WeatherData() { 11 this.observers = new ArrayList<Observer>(); 12 } 13 14 @Override 15 public void registerObserver(Observer observer) { 16 this.observers.add(observer); 17 } 18 19 @Override 20 public void removeObserver(Observer observer) { 21 this.observers.remove(observer); 22 } 23 24 @Override 25 public void notifyObservers() { 26 for (Observer observer : observers) { 27 observer.update(); 28 } 29 } 30 31 public void measurementsChanged() { 32 notifyObservers(); 33 } 34 35 public void setMeasurements(float temperature, float humidity, 36 float pressure, List<Float> forecastTemperatures) { 37 this.temperature = temperature; 38 this.humidity = humidity; 39 this.pressure = pressure; 40 this.forecastTemperatures = forecastTemperatures; 41 measurementsChanged(); 42 } 43 44 public float getTemperature() { 45 return temperature; 46 } 47 48 public float getHumidity() { 49 return humidity; 50 } 51 52 public float getPressure() { 53 return pressure; 54 } 55 56 public List<Float> getForecastTemperatures() { 57 return forecastTemperatures; 58 } 59 }
显示当前天气的公告牌CurrentConditionsDisplay
1 public class CurrentConditionsDisplay implements Observer, DisplayElement { 2 3 private WeatherData weatherData; 4 5 private float temperature;//温度 6 private float humidity;//湿度 7 private float pressure;//气压 8 9 public CurrentConditionsDisplay(WeatherData weatherData) { 10 this.weatherData = weatherData; 11 this.weatherData.registerObserver(this); 12 } 13 14 @Override 15 public void display() { 16 System.out.println("当前温度为:" + this.temperature + "℃"); 17 System.out.println("当前湿度为:" + this.humidity); 18 System.out.println("当前气压为:" + this.pressure); 19 } 20 21 @Override 22 public void update() { 23 this.temperature = this.weatherData.getTemperature(); 24 this.humidity = this.weatherData.getHumidity(); 25 this.pressure = this.weatherData.getPressure(); 26 display(); 27 } 28 }
显示未来几天天气的公告牌ForecastDisplay
1 public class ForecastDisplay implements Observer, DisplayElement { 2 3 private WeatherData weatherData; 4 5 private List<Float> forecastTemperatures;//未来几天的温度 6 7 public ForecastDisplay(WeatherData weatherData) { 8 this.weatherData = weatherData; 9 this.weatherData.registerObserver(this); 10 } 11 12 @Override 13 public void display() { 14 System.out.println("未来几天的气温"); 15 int count = forecastTemperatures.size(); 16 for (int i = 0; i < count; i++) { 17 System.out.println("第" + i + "天:" + forecastTemperatures.get(i) + "℃"); 18 } 19 } 20 21 @Override 22 public void update() { 23 this.forecastTemperatures = this.weatherData.getForecastTemperatures(); 24 display(); 25 } 26 }
下面是测试观察者模式的程序:
1 public class ObserverPatternTest { 2 3 public static void main(String[] args) { 4 5 WeatherData weatherData = new WeatherData(); 6 CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData); 7 ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData); 8 9 List<Float> forecastTemperatures = new ArrayList<Float>(); 10 forecastTemperatures.add(22f); 11 forecastTemperatures.add(-1f); 12 forecastTemperatures.add(9f); 13 forecastTemperatures.add(23f); 14 forecastTemperatures.add(27f); 15 forecastTemperatures.add(30f); 16 forecastTemperatures.add(10f); 17 weatherData.setMeasurements(22f, 0.8f, 1.2f, forecastTemperatures); 18 } 19 }
输出结果:
当前温度为:22.0℃ 当前湿度为:0.8 当前气压为:1.2 未来几天的气温 第0天:22.0℃ 第1天:-1.0℃ 第2天:9.0℃ 第3天:23.0℃ 第4天:27.0℃ 第5天:30.0℃ 第6天:10.0℃
posted on 2018-10-23 00:08 monster101 阅读(205) 评论(0) 编辑 收藏 举报