观察者模式在气象站中的运用

源码地址:
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状态发生变化时就会遍历整个集合,循环调用观察者公告牌更新数据的方法。后面如果我们需要增加或者删除公告牌就只需新增或者删除实现了ObserverDisplayElement`接口的公告牌就好了。
  观察者模式将观察者和主题(被观察者)彻底解耦,主题只知道观察者实现了某一接口(也就是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 }
View Code 

 

 观察者接口

1 **
2  * 观察者
3  */
4 public interface Observer {
5     void update();
6 }
View Code

 

公告牌用于显示的公共接口

1 public interface DisplayElement {
2     void display();
3 }
View Code

 

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 }
View Code

 

显示当前天气的公告牌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 }
View Code

 

显示未来几天天气的公告牌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 }
View Code
 
 
下面是测试观察者模式的程序:
 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 }
View Code

 

输出结果: 

当前温度为: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℃
View Code

 

posted on 2018-10-23 00:08  monster101  阅读(205)  评论(0编辑  收藏  举报

导航