Head First 设计模式笔录--观察者模式

本文详细介绍了观察者模式的原理及应用实例。通过气象站故事场景,讲解如何实现一对多依赖关系,确保当一个对象状态发生变化时,所有依赖者能够接收到通知并更新数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

观察者模式定义了一种一对多的依赖关系,当一个对象改变状态时,他的所有依赖者都会收到通知并更新数据。

比如我们常见的设置监听,button.setOnClickListener也算是观察者的一种。

核心关注点

观察者与被观察者是松耦合的,被观察者只需要知道,观察者都实现了统一的接口,都提供了update的方法。只要接口不变,改变任何一方的内容,都不会对另一方造成影响。

被观察者中持有观察者的list,发生数据变化就通知到list中的所有观察者,注意解除观察的时候及时移除观察者,避免内存泄漏.

气象站的故事情景

X公司与气象台合作,气象台会提供一个WeatherData对象,该对象会追踪当前的天气状况,温度,湿度,气压三种。要求X公司提供系统,可以接入不同的布告板展示数据,要求第三方任意公司都可以创建布告板,接入并展示气象台的数据。

我们定义了主题接口(被观察者接口),声明了添加观察者,移除观察者,通知变化的方法。同时定义一个观察者接口,声明一个更新的方法。

 图中多了display接口,考虑到不同的布告板,显示不同的样式,效果,所以这里才有了该接口。

interface Observer {
    void update(float temp, float humidity, float pressure);
}


interface DisplayElement {
    void display(float temp, float h, float p);
}


public interface Subject {
    void registObserver(Observer observer);
    void removeOBserver(Observer observer);
    void notifyOBservers();
}

数据监控对象 

class WeatherData implements Subject {
    private List<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData() {
        observers = new ArrayList<>();
    }

    @Override
    public synchronized void registObserver(Observer observer) {
        if (observers.contains(observer)) {
            return;
        }
        observers.add(observer);
    }

    @Override
    public synchronized void removeOBserver(Observer observer) {
        if (!observers.contains(observer)) {
            return;
        }
        observers.remove(observer);
    }

    @Override
    public void notifyOBservers() {
        for (Observer o : observers) {
            o.update(temperature, humidity, pressure);
        }
    }

    private void measurementChanged() {
        notifyOBservers();
    }

    public void setMeasurements(float t, float m, float p) {
        this.temperature = t;
        this.humidity = m;
        this.pressure = p;
        measurementChanged();

    }
}

布告板

class CurrentConditionDisplay implements Observer, DisplayElement {
    private WeatherData mWeatherData;

    public CurrentConditionDisplay(WeatherData weatherData) {
        this.mWeatherData = weatherData;
        weatherData.registObserver(this);
    }

    @Override
    public void display(float temp, float h, float p) {
        System.out.println("布告板展示数据:温度:" + temp + "   湿度是:" + h + "   气压是:" + p);
    }

    @Override
    public void update(float temp, float humidity, float pressure) {
        //获取到了数据,
        System.out.println("布告板收到数据更新的通知了");
        display(temp, humidity, pressure);
    }

    public void destroy() {
        mWeatherData.removeOBserver(this);
        mWeatherData = null;
    }
}
WeatherData weatherData = new WeatherData();
CurrentConditionDisplay currentConditionDisplay = new CurrentConditionDisplay(weatherData);

weatherData.setMeasurements(30f, 20f, 1.0f);

java中内置了观察者模式,但是,java内置的Observable是一个类,在java单继承的情况下,一旦继承了Observable类,就无法继承其他类了。并且内部notifyObservers的方法,需要在状态changed为true的情况下才会发送通知,而该setChanged的方法是protected的,如果不是其子类就无法调用更改状态。属实是坑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值