一、观察者模式(Observer)原理

  1、观察者模式原理

    观察者模式类似于订牛奶业务:

    (1)奶站/气象局:Subject;

    (2)用户/第三方网站:Observer

    Subject:登记注册、移除和通知

    

     (1)registerObserver 注册

    (2)removeObserver 移除

    (3)notifyObserver() 通知所有的注册的用户,根据不同需求,可以是更新数据,让用户来取,也可能是实施推送,看具体需求;

    

    Observer:接收输入

    

 

     观察者模式:对象之间多对一依赖的一种设计方案,被依赖的对象为 Subject,依赖的对象为 Observer,Subject 通知 Observer 变化,比如这里的奶站是 Subject,是 1 的一方,用户是 Observer,是多的一方。

 

二、观察者模式应用

  1、思路分析图解(类图)

    

  2、代码实现

    Subject接口

1 /**
2  *  接口,让 WeatherData 来实现
3  */
4 public interface Subject {
5 
6     public void registerObserver(Observer o);
7     public void removeObserver(Observer o);
8     public void notifyObserver();
9 }

 

    Subject实现类:

  1 /**
  2  * 核心类
  3  *  1、包含最新的天气情况信息
  4  *  2、包含 观察者集合,使用 ArrayList 管理
  5  *  3、当数据有更新时,就主动的调用 ArrayList,
  6  *      通知所有(接入方)就看到最新的信息
  7  *
  8  */
  9 public class WeatherData implements Subject{
 10 
 11     private float temperatrue;
 12     private float pressure;
 13     private float humidity;
 14 
 15     //观察者集合
 16     private ArrayList<Observer> observers;
 17 
 18     public WeatherData() {
 19         this.observers = new ArrayList<>();
 20     }
 21 
 22     /**
 23      * 注册一个观察者
 24      * @param o
 25      */
 26     @Override
 27     public void registerObserver(Observer o) {
 28         observers.add(o);
 29     }
 30 
 31     /**
 32      * 移除一个观察者
 33      * @param o
 34      */
 35     @Override
 36     public void removeObserver(Observer o) {
 37         if (observers.contains(o)) {
 38             observers.remove(o);
 39         }
 40     }
 41 
 42     //遍历所有的观察者,并通知
 43     @Override
 44     public void notifyObserver() {
 45         for (int i = 0; i < observers.size(); i++) {
 46             observers.get(i).update(temperatrue, pressure, humidity);
 47         }
 48     }
 49 
 50 
 51     /**
 52      * 当数据有更新时就调用 setData
 53      * @param temperature
 54      * @param pressure
 55      * @param humidity
 56      */
 57     public void setData(float temperature, float pressure, float humidity) {
 58         this.temperatrue = temperature;
 59         this.pressure = pressure;
 60         this.humidity = humidity;
 61         //调用 dataChange 方法,将最新信息 推送给 接入方 currentConditions
 62         dataChange();
 63     }
 64 
 65     //通知所有
 66     public void dataChange() {
 67         notifyObserver();
 68     }
 69 
 70 
 71     public float getTemperatrue() {
 72         return temperatrue;
 73     }
 74 
 75     public void setTemperatrue(float temperatrue) {
 76         this.temperatrue = temperatrue;
 77     }
 78 
 79     public float getPressure() {
 80         return pressure;
 81     }
 82 
 83     public void setPressure(float pressure) {
 84         this.pressure = pressure;
 85     }
 86 
 87     public float getHumidity() {
 88         return humidity;
 89     }
 90 
 91     public void setHumidity(float humidity) {
 92         this.humidity = humidity;
 93     }
 94 
 95     public ArrayList<Observer> getObservers() {
 96         return observers;
 97     }
 98 
 99     public void setObservers(ArrayList<Observer> observers) {
100         this.observers = observers;
101     }
102 }

 

    观察者接口Observer:

1 /**
2  * 观察者接口,由观察者来实现
3  */
4 public interface Observer {
5 
6     public void update(float temperatrue, float pressure, float humidity);
7 }

 

    观察者实现类:

 1 public class CurrentConditions implements Observer{
 2     private float temperature; //温度
 3     private float pressure;    //气压
 4     private float humidity;    // 湿度
 5 
 6 
 7     /**
 8      * 更新天气情况,是由 WeatherData 来调用,使用的是 推送模式
 9      * @param temperature
10      * @param pressure
11      * @param humidity
12      */
13     @Override
14     public void update(float temperature, float pressure, float humidity) {
15         this.temperature = temperature;
16         this.pressure = pressure;
17         this.humidity = humidity;
18         display();
19     }
20 
21 
22     /**
23      * 显示信息
24      */
25     public void display() {
26         System.out.println("***Today mTemperature: " + temperature + "***");
27         System.out.println("***Today mPressure: " + pressure + "***");
28         System.out.println("***Today mHumidity: " + humidity + "***");
29     }
30 }
31 
32 --------------------------------------------------
33 public class BaiduSite implements Observer{
34 
35     private float temperature; //温度
36     private float pressure;    //气压
37     private float humidity;    // 湿度
38 
39     @Override
40     public void update(float temperatrue, float pressure, float humidity) {
41         this.temperature = temperature;
42         this.pressure = pressure;
43         this.humidity = humidity;
44         display();
45     }
46 
47     /**
48      * 显示信息
49      */
50     public void display() {
51         System.out.println("***百度天气信息***");
52         System.out.println("***百度网站:Today mTemperature: " + temperature + "***");
53         System.out.println("***百度网站:Today mPressure: " + pressure + "***");
54         System.out.println("***百度网站:Today mHumidity: " + humidity + "***");
55     }
56 }

 

 

    客户端:

 1 public class Client {
 2     public static void main(String[] args) {
 3 
 4         //1.创建 WeatherData
 5         WeatherData weatherData = new WeatherData();
 6 
 7         //2.创建观察者
 8         CurrentConditions currentConditions = new CurrentConditions();
 9 
10         //3.注册到 weatherData 中
11         weatherData.registerObserver(currentConditions);
12 
13 
14         //再次创建观察者
15         BaiduSite baiduSite = new BaiduSite();
16         weatherData.registerObserver(baiduSite);
17 
18         //4.测试
19         System.out.println("通知各个注册的观察者,看看信息");
20 
21         weatherData.setData(10, 100, 30.3f);
22 
23 
24     }
25 }

 

 

三、观察者模式的好处

  1、观察者模式设计后,会以集合的方式来管理用户(Observer),包括注册,移除和通知;

  2、这样,我们增加观察者(这里可以理解成一个新的公告板),就不需要去修改核心类 WeatherData 不会修改代码,遵守了 OCP 原则;

 

posted on 2021-02-18 23:07  格物致知_Tony  阅读(700)  评论(0编辑  收藏  举报