10.观察者模式

文章目录


一、介绍

观察者模式是一种行为设计模式,其中一个对象(称为主题)维护其依赖项(称为观察者)的列表,当主题的状态发生变化时,它通知所有的观察者,使得它们能够自动更新。

观察者模式主要涉及三个角色:

  1. 主题(Subject): 维护一组观察者,提供方法来添加和删除观察者,以及通知观察者状态变化的方法。

  2. 观察者(Observer): 定义一个更新接口,以便主题在状态变化时能够通知观察者。

  3. 具体主题(ConcreteSubject): 继承自主题,实现具体的业务逻辑,并在状态发生变化时通知观察者。

  4. 具体观察者(ConcreteObserver): 实现观察者接口,以便在接收到通知时能够执行相应的操作。

二、代码

结构图

场景

假设我们有一个气象站,气象站会定期更新温度,湿度和气压。我们希望设计一个系统,当气象站的数据更新时,所有注册的显示器(观察者)都能够自动更新显示。

代码

java 复制代码
// 主题接口:气象站
interface WeatherStation {
    void registerObserver(WeatherObserver observer);
    void removeObserver(WeatherObserver observer);
    void notifyObservers();
}
java 复制代码
// 观察者接口:显示器
interface WeatherObserver {
    void update(float temperature, float humidity, float pressure);
}
java 复制代码
// 具体主题:具体的气象站
class ConcreteWeatherStation implements WeatherStation {
    private List<WeatherObserver> observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public ConcreteWeatherStation() {
        this.observers = new ArrayList<>();
    }

    @Override
    public void registerObserver(WeatherObserver observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(WeatherObserver observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (WeatherObserver observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }

    // 模拟气象站数据更新
    public void setWeatherData(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        notifyObservers();
    }
}
java 复制代码
// 具体观察者1:温度显示器
class TemperatureDisplay implements WeatherObserver {
    @Override
    public void update(float temperature, float humidity, float pressure) {
        System.out.println("Temperature Display: Current Temperature = " + temperature);
    }
}

// 具体观察者2:湿度显示器
class HumidityDisplay implements WeatherObserver {
    @Override
    public void update(float temperature, float humidity, float pressure) {
        System.out.println("Humidity Display: Current Humidity = " + humidity);
    }
}
java 复制代码
// 客户端
public class ObserverPatternExample {
    public static void main(String[] args) {
        ConcreteWeatherStation weatherStation = new ConcreteWeatherStation();

        // 注册观察者
        WeatherObserver temperatureDisplay = new TemperatureDisplay();
        WeatherObserver humidityDisplay = new HumidityDisplay();
        weatherStation.registerObserver(temperatureDisplay);
        weatherStation.registerObserver(humidityDisplay);

        // 模拟气象站数据更新,观察者自动更新显示
        weatherStation.setWeatherData(25.5f, 60.0f, 1012.0f);

        // 移除一个观察者
        weatherStation.removeObserver(temperatureDisplay);

        // 模拟气象站数据更新,仅湿度显示器会更新
        weatherStation.setWeatherData(26.0f, 65.0f, 1010.5f);
    }
}

在客户端,我们创建了一个具体的气象站对象,并注册了温度显示器和湿度显示器作为观察者。随后,通过模拟气象站数据的更新,观察者自动更新了显示


总结

优点

  1. 松耦合: 观察者模式实现了目标和观察者之间的松耦合。主题(目标)和观察者之间相互独立,它们只是通过接口进行通信。

  2. 可扩展性: 新的观察者可以随时被加入到系统中,而无需修改主题的代码。这使得系统更容易扩展和维护。

  3. 通知机制: 主题发生变化时,会自动通知所有的观察者。这种通知机制使得观察者能够实时获取目标的最新状态。

缺点

  1. 可能引起性能问题: 如果观察者非常多,而且通知频繁,可能会影响性能。因为每个观察者都需要被通知,而且通知是同步的。

  2. 可能导致循环依赖: 当观察者之间存在相互依赖时,可能导致循环依赖的问题。这样的情况下,系统可能需要被重新设计。

  3. 可能造成内存泄漏: 如果观察者没有被正确地移除,可能导致对观察者的引用一直存在,造成内存泄漏。

相关推荐
gadiaola24 分钟前
【JVM】Java虚拟机(二)——垃圾回收
java·jvm
coderSong25683 小时前
Java高级 |【实验八】springboot 使用Websocket
java·spring boot·后端·websocket
Mr_Air_Boy4 小时前
SpringBoot使用dynamic配置多数据源时使用@Transactional事务在非primary的数据源上遇到的问题
java·spring boot·后端
豆沙沙包?4 小时前
2025年- H77-Lc185--45.跳跃游戏II(贪心)--Java版
java·开发语言·游戏
年老体衰按不动键盘5 小时前
快速部署和启动Vue3项目
java·javascript·vue
咖啡啡不加糖5 小时前
Redis大key产生、排查与优化实践
java·数据库·redis·后端·缓存
liuyang-neu5 小时前
java内存模型JMM
java·开发语言
UFIT5 小时前
NoSQL之redis哨兵
java·前端·算法
刘 大 望5 小时前
数据库-联合查询(内连接外连接),子查询,合并查询
java·数据库·sql·mysql
怀旧,5 小时前
【数据结构】6. 时间与空间复杂度
java·数据结构·算法