当前位置: 首页 > article >正文

23中设计模式之观察者模式

观察者模式说明

观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当主题对象发生变化时,它的所有依赖者(观察者)都会收到通知并自动更新。在Java中,观察者模式可以通过使用java.util.Observable类和java.util.Observer接口来实现,不过自Java 9起,这两个类被标记为过时,推荐使用更灵活的设计模式或库来实现相同的功能

应用场景

  • 订单状态变更时通知库存、物流、用户通知等子系统
  • 配置变更时,所有微服务实时更新配置。
  • 用户注册成功后发送邮件、初始化数据

优点

  1. 促进松耦合:主题只知道观察者实现了某个接口,而不需要知道观察者的具体类是谁、做了何种操作等细节。这使得你可以独立地改变主题或观察者中的一个,而不会影响另一个。
  2. 支持广播通信:不需要指定具体的观察者,主题可以将消息发送给所有注册的观察者,实现广播机制。
  3. 易于扩展:新增观察者非常容易,无需修改主题代码,只需实现观察者接口即可。

缺点

  1. 可能导致内存泄漏:如果观察者没有正确移除自己,可能会导致主题持有对已销毁观察者的引用,从而阻止垃圾回收器回收它们,造成内存泄漏。
  2. 难以追踪依赖关系:由于观察者和被观察者之间是通过接口连接的,所以很难直观地看出系统中到底有多少观察者依赖于某个主题,这增加了调试的难度。
  3. 潜在性能问题:如果有大量的观察者,通知所有观察者的过程可能会变得很慢。此外,如果通知链设计不当,还可能引起循环调用的问题。

总的来说,观察者模式非常适合处理当一个对象的状态变化需要触发其他对象进行相应变化的情况。然而,在使用该模式时也需要注意其可能带来的缺点,如内存管理、性能优化以及依赖关系的复杂性等问题。合理的设计和适当的优化可以帮助克服这些问题。

观察者模式的组成

  • Subject(主题):维护了一个观察者列表,并提供添加、删除和通知观察者的方法。
  • Observer(观察者):定义了更新接口,用于接收来自主题的通知。
  • ConcreteSubject(具体主题):继承自Subject,包含了状态信息,这些状态变化会通知给观察者。
  • ConcreteObserver(具体观察者):实现了Observer接口,用来保持与主题相关的状态,并在主题状态改变时进行自身状态的更新。

观察者模式 Demo

观察者接口及实现类

定义一个观察者接口:

/**
 * 观察者接口
 *
 * @version 1.0
 * @since 2025/03/04
 **/
public interface Observer {
    // 接收更新
    void update(float temperature, float humidity);
}

定义一个观察者接口的实现类:

/**
 * 当天天气显示-实现观察者
 *
 * @version 1.0
 * @since 2025/03/04
 **/
public class CurrentConditionsDisplay implements Observer{
    private float temperature;
    private float humidity;

    @Override
    public void update(float temperature, float humidity) {
        this.temperature = temperature;
        this.humidity = humidity;
        // 更新后显示数据
        display();
    }

    public void display() {
        System.out.println("Current conditions: " + temperature + "°C and " + humidity + "% humidity");
    }
}

被观察者接口及实现类

定义一个被观察者接口:

/**
 * 被观察者接口
 *
 * @version 1.0
 * @since 2025/03/04
 **/
public interface WeatherStation {
    // 注册观察者
    void registerObserver(Observer observer);
    // 移除观察者
    void removeObserver(Observer observer);
    // 通知所有观察者
    void notifyObservers();
}

定义一个被观察者接口的实现类:

/**
 * 实现观察者
 *
 * @version 1.0
 * @since 2025/03/04
 **/
public class CurrentConditionsDisplay implements Observer{
    private float temperature;
    private float humidity;

    @Override
    public void update(float temperature, float humidity) {
        this.temperature = temperature;
        this.humidity = humidity;
        // 更新后显示数据
        display();
    }

    public void display() {
        System.out.println("Current conditions: " + temperature + "°C and " + humidity + "% humidity");
    }
}

测试代码:

/**
 * 测试代码
 *
 * @version 1.0
 * @since 2025/03/04
 **/
public class WeatherTest {

    public static void main(String[] args) {
        // 创建天气预报站
        ConcreteWeatherStation weatherStation = new ConcreteWeatherStation();

        // 创建观察者(显示屏)
        CurrentConditionsDisplay display1 = new CurrentConditionsDisplay();
        CurrentConditionsDisplay display2 = new CurrentConditionsDisplay();

        // 注册观察者
        weatherStation.registerObserver(display1);
        weatherStation.registerObserver(display2);

        // 发布新数据
        // 输出两个显示屏的数据
        System.out.println("------------------------------------------------------------------------");
        weatherStation.setMeasurements(25.0f, 60.0f);
        // 再次更新数据
        weatherStation.setMeasurements(30.0f, 70.0f);
    }
}

输出结果

------------------------------------------------------------------------
Current conditions: 25.0°C and 60.0% humidity
Current conditions: 25.0°C and 60.0% humidity
Current conditions: 30.0°C and 70.0% humidity
Current conditions: 30.0°C and 70.0% humidity

PS:
如果你看到这里,希望我的分享,可以帮到你,感谢你的阅读,愿我们在代码世界变得更强!


http://www.kler.cn/a/574500.html

相关文章:

  • 计算机基础:二进制基础05,八进制简介
  • 如何在WPS中接入DeepSeek并使用OfficeAI助手(超细!成功版本)
  • 【硬件IIC与软件IIC在程序实现上的核心区别】结合STM32F103C8T6标准库代码进行对比分析
  • EasyDSS视频推拉流/直播点播平台:Mysql数据库接口报错502处理方法
  • Python 高级图表绘制秘籍: Matplotlib 与 Seaborn 热力图、箱线图实战
  • 初探 Mercury:首个商业级扩散大语言模型的初步观察与体验
  • 绝美焦糖暖色调复古风景画面Lr调色教程,手机滤镜PS+Lightroom预设下载!
  • 微服务拆分-拆分商品服务
  • 字节跳动AI原生编程工具Trae和百度“三大开发神器”AgentBuilder、AppBuilder、ModelBuilder的区别是?
  • 使用Kingfisher加载网络图片时使用indicatorType产生布局混乱
  • 【有啥问啥】深入浅出:大模型应用工具 Ollama 技术详解
  • 属于网络安全规划重安全性需求
  • JAVA编程【jvm垃圾回收的差异】
  • 【Linux】vim使用与配置教程
  • 杨校老师课堂之备战信息学奥赛算法背包DP练习题汇总
  • SQL Server查询计划操作符(7.3)——查询计划相关操作符(8)
  • RocksDB
  • 计算机毕业设计SpringBoot+Vue.js客户关系管理系统CRM(源码+文档+PPT+讲解)
  • 实验一:在Windows 10/11下配置和管理TCP/IP
  • 用DeepSeek搭建一个免费的AI智能量化机器人