观察者模式简单例子

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

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

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

/**
 * 气象站实现主题,发布气象信息(气温)
 */
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();
    }
}
/**
 * 布告板上的状态显示
 */
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();
    }
}

测试结果

/**
 * 天气观测站
 */
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);
    }
}

这里写图片描述

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);
    }
}
/**
 * 实现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();
        }
    }
}

测试运行结果

/**
 * 天气观测站
 */
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);
    }
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值