打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
观察者模式简单例子

观测者模式定义了对象之间的一对多依赖,当一个对象状态发生改变时,其依赖者便会收到通知并做相应的更新。其原则是:为交互对象之间松耦合。以松耦合方式在一系列对象之间沟通状态,我们可以独立复用主题(Subject)/可观测者(Observable)和观测者(Observer),即只要遵守接口规则改变其中一方并不会影响到另一方。这也是其主要的设计原则。下面是一个简单的气象站发送天气信息给布告板,然后布告板把天气信息显示在板上的例子。
首先先建立三个接口,主题(Subject)、观测者(Observer)和显示内容(DisplayElement),分别代表气象站、布告板信息接收和布告板信息显示。

/** *  主题 */public interface Subject {    // 观察者注册    public void registerObserver(Observer o);    // 删除观察者    public void removeObserver(Observer o);    // 当主题有内容更新时调用,用于通知观察者    public void notifyObserver();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
/** *  观察者 */public interface Observer {    // 当气象站观测的天气发生变化时,主题会把参数值传给观察者    public void update(float temp);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
/** *  用于布告板显示 */public interface DisplayElement {    // 在显示布告板上显示的操作    public void display();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

接下来是实现气象站()和布告板()了。

/** * 气象站实现主题,发布气象信息(气温) */public class WeatherStation implements Subject{    private ArrayList observers;    private float temp;    public WeatherStation() {        // 加个ArrayList存放所有注册的Observer对象;        observers = new ArrayList<>();    }    @Override    public void registerObserver(Observer o) {        // 当新的观察者注册时添加进来        observers.add(o);    }    @Override    public void removeObserver(Observer o) {        // 当观察者取消注册时去除该观察者        int i = observers.indexOf(o);        if (i>=0) {            observers.remove(i);        }    }    @Override    public void notifyObserver() {        // 更新状态,调用Observer的update告诉观察者有新的信息        for (int i = 0; i < observers.size(); i++) {            Observer observer = (Observer) observers.get(i);            observer.update(temp);        }    }    /*     *  此方法用于气象站收到的数据,并且调用更新使数据实时通知给观察者     */    public void setMeasurements(float temp){        this.temp = temp;        System.out.println("气象站测量的温度为:" + temp + "℃");        notifyObserver();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
/** * 布告板上的状态显示 */public class ConditionDisplay implements Observer,DisplayElement{    private float temp;    private Subject weatherStation;    public ConditionDisplay(Subject weatherStation) {        // 构造时需要间主题/被观察者对象作为注册之用        this.weatherStation = weatherStation;        weatherStation.registerObserver(this);    }    @Override    public void display() {        // 将数据显示在布告板上        System.out.println("布告板显示当前温度为:" + temp + "℃");    }    @Override    public void update(float temp) {        // 接受来自主题/被观察者(气象站)的数据        this.temp = temp;        display();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

测试结果

/** * 天气观测站 */public class WeatherObserver {    public static void main(String[] args) {        // 首先创建一个主题/被观察者        WeatherStation weatherStation = new WeatherStation();        // 创建观察者并将被观察者对象传入        ConditionDisplay conditionDisplay = new ConditionDisplay(weatherStation);        // 设置气象站模拟收到的气温数据        weatherStation.setMeasurements(25);        weatherStation.setMeasurements(24);        weatherStation.setMeasurements(23);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

JAVA内置观察者模式
可以使用java内置的观察者模式,这样就无需自己写Subject和Observer类了,在java.util包下继承的Observable和实现Observer类即可。其修改后的代码如下:

/** * 继承java内置的被观察者,因此不再需要注册和删除了 */public class WeatherStationN extends Observable{    private float temperature;    public WeatherStationN() {        // 由于继承了Observable,它已经创建了一个Vector来存放Observer对象的容器,所以此处不用再建立ArrayList    }    /*     *  此方法用于气象站收到的数据,并且调用更新使数据实时通知给观察者     */    public void setMeasurements(float temp){        this.temperature = temp;        System.out.println("气象站测量的温度为:" + temp + "℃");        // 更新强调用表示有状态更新        setChanged();        notifyObservers(temperature);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
/** * 实现java内置Observer接口 */public class ConditionDisplayN implements java.util.Observer,DisplayElement{    private Observable observable;    private float temp;    public ConditionDisplayN(Observable observable) {        // 构造器需要Observable作为参数        this.observable = observable;        observable.addObserver(this);    }    @Override    public void display() {        // 将数据显示在布告板上        System.out.println("布告板显示当前温度为:" + temp + "℃");    }    @Override    public void update(Observable o, Object arg) {        // 当被观察者有更新使触发        if (o instanceof WeatherStationN) {            this.temp = (float) arg;            display();        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

测试运行结果

/** * 天气观测站 */public class WeatherObserver {    public static void main(String[] args) {        // 首先创建一个主题/被观察者        WeatherStationN weatherStationN = new WeatherStationN();        // 创建观察者并将被观察者对象传入        ConditionDisplayN conditionDisplayN = new ConditionDisplayN(weatherStationN);        // 设置气象站模拟收到的气温数据        weatherStationN.setMeasurements(30);        weatherStationN.setMeasurements(25);        weatherStationN.setMeasurements(20);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17


注意:
Observer是一个接口,而Observable是一个类,在使用时必须继承它,因此在继承Observable时就无法再继承其他超类了,因为Java毕竟不支持多重继承。且在Observable更新前,即notifyObservers()或notifyObservers(Object arg)前要先调用setChange()标记更新状态

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
图解Java设计模式之观察者模式
设计模式之观察者模式(二)
设计模式读书笔记-----观察者模式
给 Android 开发者的 RxJava 详解
观察者模式(bqlr)
使用Observer模式
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服