观察者模式 (Java内置观察者模式以及扩展)


什么是观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。

优点:

1、观察者和被观察者是抽象耦合的。
2、建立一套触发机制。

缺点:

1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

公众号 实例UML图

在这里插入图片描述

Observable 被观察者

直接使用java内置的Observable类
里面有一系列方法:
    1. addObserver 添加观察员
    2. deleteObserver 删除观察员
    3. notifyObservers 通知观察员
    4. notifyObservers(Observer) 通知某个观察员
    5. deleteObservers 删除所有观察员
    6. setChangeed 改变信号

在这里插入图片描述
在这里插入图片描述

WeatherData 具体被观察者

具体被观察者要点:
    1. 需要一个集合去存放 观察者
    2. 继承Observable
    3. 拥有一个修改数据的方法setMeasurements

public class WeatherData extends Observable{
    /**
     *具体的Observable中会有
     *  add
     *  delete
     *  notify方法
     */
    //内置一个存储集合
    private List<Weather> weathers = new Vector<>();

    private float temperature;

    private float humidity;

    private float pressure;

    public WeatherData() {}

    /**
     * 数据修改 并且通知
     */
    public void measurementsChanged(){
        //调用notifyObservers 之前需要先 修改指示状态。 change = true
        setChanged();
        //修改的次数计数器
        count++;
        //notifyObservers() 传送数据对象,这代表我们是 “拉”
        notifyObservers();
    }

    public void setMeasurements(float temperature,float humidity,float pressure){
        Weather weather = new Weather(temperature, humidity, pressure);
        weathers.add(weather);
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }

    /**
    * 通过这些方法 观察者会利用他们去拉取 获得WeatherData的状态
    */
    public float getTemperature() {
        return temperature;
    }

    public float getPressure() {
        return pressure;
    }

    public float getHumidity() {
        return humidity;
    }

    @Override
    public List<Weather> getWeathers() {
        return weathers;
    }

    @Override
    public Integer getCountObservers() {
        return count;
    }
}

Observer 观察者接口

被观察者对 观察者接口 进行组合

public interface Observer {
    void update(Observable o, Object arg);
}

当调用Observable的notifyObservers方法时,进行调用update更新消息。

public void notifyObservers(Object arg) {
       
        Object[] arrLocal;

        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

DisplayElement接口 对观察者的行为进行扩展

public interface DisplayElement {

    public void display();
}

GeneralDisplay 具体观察者

使得具体观察者去实现 观察者接口 和 扩展接口
并且对Observable被观察者进行组合

public class GeneralDisplay implements Observer, DisplayElement {
    Observable observable;
    private float temperature;
    private float humidity;

    public GeneralDisplay(Observable observable){
        this.observable = observable;
        observable.addObserver(this);
    }

    @Override
    public void display() {
        System.out.println("General平台 ↓ \n温度为:"+temperature +" , 湿度为: "+humidity);
    }

    @Override
    public void update(Observable o, Object arg) {
        if (o instanceof WeatherData){
            WeatherData weatherData = (WeatherData) o;
            this.temperature = weatherData.getTemperature();
            this.humidity = weatherData.getHumidity();
            display();
        }
    }
}

测试类

    public static void main(String[] args) {
        //公众号
        WeatherData weatherData = new WeatherData();

        //个人公众号
        new GeneralDisplay(weatherData);
        new SpecialDisplay(weatherData);

        //进行更新信息
        weatherData.setMeasurements(30,60,66);

        Integer countObservers = weatherData.getCountObservers();
        System.out.println("修改数据次数为:"+countObservers);

        List<Weather> weathers = weatherData.getWeathers();
        System.out.println("以往数据为:"+weathers);

        int i = weatherData.countObservers();
        System.out.println("平台数为:"+i);
    }

在这里插入图片描述

随之而来的问题

Java内置对象 Observable是类,这违反了面向接口编程的原则,限制了他的复用和使用。
并且其中setChange方法是protected,这意味的你必须继承Observable类,但是Java中不支持类的多继承,这违反了第二个设计原则“多用组合,少用继承

如何解决?

1. 我们自己去实现一套观察者模式。
2. 扩展Observable类。

如何扩展 加一层(这是我的想法,不对可以指出)

我的理解而言如果要使用 java内置对象Observable的话
我会去尝试加一层

public abstract class ObservableAbstract extends Observable {

    /**
    * @Author JMWANG
    * @Description 如果使用还需要一个外置 的 ArrayList集合 在子类中写
    */
    public abstract List<Weather> getWeathers();

    //计数器专门记录 数据修改次数
    public int count;

    public abstract Integer getCountObservers();

}

我让 具体观察者直接继承我的抽象类ObservableAbstract
我设计抽象类ObservableAbstract 就是为了进行扩展,这的确无法解决以上的问题,但是我可以使用扩展,去进行功能的扩展。

又或者我会在 观察者接口下 继续加层实现多功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小小狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值