10.观察者模式


一、介绍

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

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

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

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

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

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

二、代码

结构图

在这里插入图片描述

场景

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

代码

// 主题接口:气象站
interface WeatherStation {
   
    void registerObserver(WeatherObserver observer);
    void removeObserver(WeatherObserver observer);
    void notifyObservers();
}
// 观察者接口:显示器
interface WeatherObserver {
   
    void update(float temperature, float humidity, float pressure);
}
// 具体主题:具体的气象站
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();
    }
}
// 具体观察者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);
    }
}
// 客户端
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. 可能造成内存泄漏: 如果观察者没有被正确地移除,可能导致对观察者的引用一直存在,造成内存泄漏。

相关推荐

  1. 设计模式(16):观察模式

    2024-01-09 07:32:02       16 阅读
  2. 【设计模式12、observer 观察模式

    2024-01-09 07:32:02       12 阅读
  3. C++11改进观察模式

    2024-01-09 07:32:02       33 阅读
  4. 观察模式 Observer

    2024-01-09 07:32:02       42 阅读
  5. 观察模式学习

    2024-01-09 07:32:02       35 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-09 07:32:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-09 07:32:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-09 07:32:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-09 07:32:02       20 阅读

热门阅读

  1. 【国标】点播与对讲的sip流

    2024-01-09 07:32:02       32 阅读
  2. huggingface实战bert-base-chinese模型(训练+预测)

    2024-01-09 07:32:02       33 阅读
  3. 实验五:动态路由配置

    2024-01-09 07:32:02       37 阅读
  4. 实验四:静态路由配置

    2024-01-09 07:32:02       34 阅读
  5. 传统图像处理学习笔记更新中

    2024-01-09 07:32:02       33 阅读
  6. 正则表达式

    2024-01-09 07:32:02       32 阅读
  7. css——box-shadow阴影效果

    2024-01-09 07:32:02       36 阅读
  8. 开源软件运维安全防护的六个手段

    2024-01-09 07:32:02       38 阅读
  9. redis原子命令和 lua 脚本解决并发问题

    2024-01-09 07:32:02       37 阅读