java23种设计模式-观察者模式
观察者模式(Observer Pattern)学习笔记
编程相关书籍分享:https://blog.csdn.net/weixin_47763579/article/details/145855793
DeepSeek使用技巧pdf资料分享:https://blog.csdn.net/weixin_47763579/article/details/145884039
1. 模式定义
行为型设计模式,定义对象间的一种一对多依赖关系,当一个对象状态发生改变时,所有依赖它的对象都会得到通知并自动更新。又称为发布-订阅模式。
2. 适用场景
✅ 需要实现事件触发机制
✅ 存在多个对象依赖一个对象状态的场景
✅ 需要实现广播通信机制
✅ 需要解耦观察者与被观察者
✅ 需要动态增减观察者对象
3. 模式结构
4. 核心角色
角色 | 说明 |
---|---|
Subject | 抽象主题(被观察者),定义注册、删除、通知观察者的接口 |
ConcreteSubject | 具体主题,维护观察者列表,状态改变时通知所有观察者 |
Observer | 抽象观察者,定义更新接口 |
ConcreteObserver | 具体观察者,实现更新逻辑 |
5. 代码示例
5.1 气象站监控示例
// 抽象主题
interface WeatherSubject {void registerObserver(WeatherObserver o);void removeObserver(WeatherObserver o);void notifyObservers();
}// 具体主题
class WeatherStation implements WeatherSubject {private List<WeatherObserver> observers = new ArrayList<>();private float temperature;private float humidity;public void setMeasurements(float temp, float humidity) {this.temperature = temp;this.humidity = humidity;notifyObservers();}public void registerObserver(WeatherObserver o) {observers.add(o);}public void removeObserver(WeatherObserver o) {observers.remove(o);}public void notifyObservers() {for (WeatherObserver o : observers) {o.update(temperature, humidity);}}
}// 抽象观察者
interface WeatherObserver {void update(float temp, float humidity);
}// 具体观察者
class CurrentConditionsDisplay implements WeatherObserver {public void update(float temp, float humidity) {System.out.printf("当前天气状况:温度%.1f℃ 湿度%.1f%%\n", temp, humidity);}
}class StatisticsDisplay implements WeatherObserver {public void update(float temp, float humidity) {// 实现统计逻辑System.out.println("更新统计数据显示...");}
}// 客户端
public class Client {public static void main(String[] args) {WeatherStation station = new WeatherStation();WeatherObserver currentDisplay = new CurrentConditionsDisplay();WeatherObserver statisticsDisplay = new StatisticsDisplay();station.registerObserver(currentDisplay);station.registerObserver(statisticsDisplay);station.setMeasurements(25.5f, 65.0f);/* 输出:当前天气状况:温度25.5℃ 湿度65.0%更新统计数据显示... */}
}
6. 模式变种
6.1 推拉模型对比
模型类型 | 数据传递方式 | 特点 |
---|---|---|
推 | 主题主动发送完整数据给观察者 | 观察者被动接收,可能收到不需要的数据 |
拉 | 观察者主动从主题获取所需数据 | 需要时获取,减少不必要数据传输 |
// 拉模型实现示例
interface PullObserver {void update(WeatherSubject subject);
}class PullWeatherDisplay implements PullObserver {public void update(WeatherSubject subject) {if (subject instanceof WeatherStation) {WeatherStation ws = (WeatherStation)subject;System.out.println("温度:" + ws.getTemperature());}}
}
7. 优缺点分析
✔️ 优点:
- 实现松耦合
- 支持动态添加/删除观察者
- 符合开闭原则
- 支持广播通信
❌ 缺点:
- 通知顺序不可控
- 观察者过多时影响性能
- 循环依赖可能导致系统崩溃
- 观察者可能收到不相关通知
8. 相关模式对比
模式 | 目的 | 关键区别 |
---|---|---|
发布-订阅模式 | 消息通知机制 | 通过消息代理解耦,支持更复杂路由 |
中介者模式 | 对象间交互 | 集中控制通信,观察者模式是分布式通知 |
责任链模式 | 请求传递 | 观察者模式是单向通知机制 |
9. 实际应用案例
- Java Swing的事件监听机制(
ActionListener
) - Spring框架的
ApplicationEvent
和ApplicationListener
- Android的
BroadcastReceiver
- JavaBeans的
PropertyChangeListener
- Reactor编程模型
- Vue.js的响应式系统
- Kafka消息队列
10. 最佳实践建议
- 使用Java内置实现:
// Java 9之前可用(已过时)
import java.util.Observable;
import java.util.Observer;// Java 9+推荐使用PropertyChangeSupport
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
- 防止内存泄漏:
// 及时移除观察者
subject.addObserver(observer);
// ...
subject.deleteObserver(observer);
- 异步通知优化:
// 使用线程池异步通知
ExecutorService executor = Executors.newCachedThreadPool();
public void notifyObservers() {for (Observer o : observers) {executor.submit(() -> o.update(data));}
}
- 使用弱引用(WeakReference):
// 防止观察者无法被垃圾回收
List<WeakReference<Observer>> weakObservers = new ArrayList<>();public void registerObserver(Observer o) {weakObservers.add(new WeakReference<>(o));
}
- 事件过滤机制:
// 添加事件类型过滤
interface EventObserver {void update(EventType type, Object data);
}enum EventType { TEMP_CHANGE, HUMIDITY_CHANGE }
11. 扩展应用(Spring事件机制)
// 自定义事件
public class OrderCreatedEvent extends ApplicationEvent {private Order order;public OrderCreatedEvent(Object source, Order order) {super(source);this.order = order;}// getter...
}// 事件发布者
@Service
class OrderService {@Autowiredprivate ApplicationEventPublisher publisher;public void createOrder(Order order) {// 创建订单逻辑...publisher.publishEvent(new OrderCreatedEvent(this, order));}
}// 事件监听者
@Component
class NotificationService {@EventListenerpublic void handleOrderCreated(OrderCreatedEvent event) {// 发送通知逻辑...}
}
🔍 设计原则体现:
- 开闭原则(OCP):新增观察者无需修改主题
- 松耦合原则:主题与观察者互相不知道对方细节
- 单一职责原则:主题管理状态,观察者处理通知
通过观察者模式,可以实现高效的事件通知机制,特别适合需要实现实时数据同步、事件驱动架构的场景。该模式在GUI开发、分布式系统和框架设计中应用广泛,是解耦组件关系的经典解决方案。
相关文章:
java23种设计模式-观察者模式
观察者模式(Observer Pattern)学习笔记 编程相关书籍分享:https://blog.csdn.net/weixin_47763579/article/details/145855793 DeepSeek使用技巧pdf资料分享:https://blog.csdn.net/weixin_47763579/article/details/145884039 1.…...
【MySQL 一 数据库基础】深入解析 MySQL 的索引(3)
索引 索引操作 自动创建 当我们为一张表加主键约束(Primary key),外键约束(Foreign Key),唯一约束(Unique)时,MySQL会为对应的的列自动创建一个索引;如果表不指定任何约束时,MySQL会自动为每一列生成一个索引并用ROW_I…...
本地部署 deepseek-r1 1.5B方法-ubuntu20.04 python3.10 pycharm虚拟环境
1. 环境安装 ubuntu20.04 python3.10 pycharm虚拟环境 2.拉取代码 虚拟环境下安装vllm: pip install vllm ubuntu命令窗口安装 sudo apt install git-lfs 初始化 Git LFS 安装 Git LFS 后,你需要虚拟环境命令窗口初始化它:git lfs i…...
【Qt】为程序增加闪退crash报告日志
背景 随着软件代码量的增加,软件崩溃闪退的肯能行越来越大,其中一些是难以复现的,比如访问了访问了非法地址、被操作系统杀死等。 为此,在软件出现闪退情况时,尽可能多的记录闪退发生时信息,对排查闪退原…...
Visual Studio打开文件后,中文变乱码的解决方案
文件加载 使用Unicode(UTF-8)编码加载文件 C:\WorkSpace\Assets\Scripts\UI\View\ExecuteComplateView.cs时,有些字节已用Unicode替换字符替换。保存该文件将不会保留原始文件内容。...
某住宅小区地下车库安科瑞的新能源汽车充电桩的配电设计与应用方案 安科瑞 耿笠
摘要:纯电动商用车的工作环境存在路况复杂、工况恶劣等情况,导致整车电气设备的磨损速率加快,造成电气设备绝缘电阻持续下降,如不及时处理,可能存在安全隐患或引发重大安全事故。文章从绝缘故障检测原理出发࿰…...
eclogy后台运维笔记(写的很乱,只限个人观看)
组织权限: 矩阵管理 这个很重要,比如进行流程操作者的选择时,我们进行需要选择财务部的出纳,会计,总经理。我们不能去直接选定一个人,万一这个人离职了,那所有的流程都要手动修改,…...
结构型模式 - 适配器模式 (Adapter Pattern)
结构型模式 - 适配器模式 (Adapter Pattern) 适配器模式是一种结构型设计模式,它允许将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 类适配器,适用于要适配的类是一个接口…...
[2/11]C#性能优化-不要使用空析构函数-每个细节都有示例代码
前言 在C#开发中,性能优化是提升系统响应速度和资源利用率的关键环节。 当然,同样是所有程序的关键环节。 通过遵循下述建议,可以有效地减少不必要的对象创建,从而减轻GC的负担,提高应用程序的整体性能。记住…...
0-基于强化学习的图Transformer算法求解车辆路径问题(2023)
文章目录 Abstract1 Introduction2. Related Work2.1 引言2.2.基于RNN的VRP解决方案2.3.基于GNN的VRP解决方案2.4.基于Transformer的车辆路径问题求解方法3 边嵌入注意力模型3.1 编码器3.1.1 边嵌入多头注意力3.1.2. 前馈网络(FFN)、批量归一化和残差连接3.2 解码器3.2.1 解码…...
Linux:互斥
目录 一、互斥概念 二、互斥的使用函数 三、互斥的底层原理 一、互斥概念 互斥,全称是线程互斥,互斥是一套解决方案,用来保护临界资源。一般在多线程的代码中,要使用互斥这套解决方案来保护临界资源。 主要从代码的角度理解互斥…...
单例模式——c++
一个类,只能有1个对象 (对象在堆空间) 再次创建该对象,直接引用之前的对象 so构造函数不能随意调用 so构造函数私有 so对象不能构造 如何调用私有化的构造函数: 公开接口调用构造函数 调用构造函数:singleTon instance; 但…...
C++之string类的模拟实现(超详细)
们学习东西,先学习如果使用它,然后再学习如何实现它 文章目录 目录 1. 命名空间以及头文件 2.string类的成员变量 3.string类的成员函数 3.1 构造函数 3.2 析构函数 3.3 拷贝构造函数 3.4 赋值运算符重载 3.5 c_str函数 3.6 size函数 3.7 clea…...
【Git 学习笔记_27】DIY 实战篇:利用 DeepSeek 实现 GitHub 的 GPG 密钥创建与配置
文章目录 1 前言2 准备工作3 具体配置过程3.1. 本地生成 GPG 密钥3.2. 导出 GPG 密钥3.3. 将密钥配置到 Git 中3.4. 测试提交 4 问题排查记录5 小结与复盘 1 前言 昨天在更新我的第二个 Vim 专栏《Mastering Vim (2nd Ed.)》时遇到一个经典的 Git 操作问题:如何在 …...
【原创工具】同文件夹PDF文件合并 By怜渠客
【原创工具】同文件夹PDF文件合并 By怜渠客 原贴:可批量合并多个文件夹内的pdf工具 - 吾爱破解 - 52pojie.cn 他这个存在一些问题,并非是软件内自主实现的PDF合并,而是调用的pdftk这一工具,但楼主并没有提供pdftk,而…...
kafka-leader -1问题解决
一. 问题: 在 Kafka 中,leader -1 通常表示分区的领导者副本尚未被选举出来,或者在获取领导者信息时出现了问题。以下是可能导致出现 kafka leader -1 的一些常见原因及相关分析: 1. 副本同步问题: 在 Kafka 集群中&…...
图像融合+语义
图像配准+融合语义方法总结 1.Joint framework of image registration and fusion RFNet: Unsupervised Network for Mutually Reinforcing Multi-modal Image Registration and Fusion(2022CVPR) Unsupervised misaligned infrared and visible image fusion via…...
AI人工智能机器学习之监督学习和集成学习
1、概要 本篇学习AI人工智能机器监督学习框架下的集成学习,以鸢尾花iris数据集、随机森林模型和梯度提升为示例,从代码层面测试和讲述监督学习和集成学习能。 2、监督学习和集成学习 - 简介 监督学习和集成学习是机器学习领域中的两个重要概念。 监督…...
通过返回的key值匹配字典中的value值
需求 页面中上面搜索项有获取字典枚举接口,table表格中也有根据key匹配字典中的value 方案一 需要做到的要求 这里上面下拉列表是一个组件获取的字典,下面也是通过字典匹配,所以尽量统一封装一个函数,每个组件保证最少变动tabl…...
30 分钟从零开始入门 CSS
HTML CSS JS 30分钟从零开始入门拿下 HTML_html教程-CSDN博客 30 分钟从零开始入门 CSS-CSDN博客 JavaScript 指南:从入门到实战开发-CSDN博客 前言 最近也是在复习,把之前没写的博客补起来,之前给大家介绍了 html,现在是 CSS 咯…...
矩阵的奇异值(SVD)分解和线性变换
矩阵的奇异值(SVD)分解和线性变换 SVD定义 奇异值分解(Singular Value Decomposition,简称 SVD)是一种重要的线性代数工具,能够将任意矩阵 ( A ∈ R m n \mathbf{A} \in \mathbb{R}^{m \times n} A∈Rmn…...
Kubernetes与Docker:区别与优劣总结
在云原生技术栈中,Docker和Kubernetes是两大核心工具,但它们的功能定位和使用场景截然不同。本文将从技术原理、架构设计、功能特性及适用场景等角度,深入分析两者的区别与优劣,并结合实际应用场景说明如何协同使用。 一、核心技术…...
表单验证和正则表达式
表单验证 表单:收集用户信息,并把信息发送给服务器程序进行处理 what 验证数据的格式,将符合标准数据格式要求的数据,发送给后台。 对用户的输入做格式校验,确保能够发送到后台服务器的数据一定是正确的。降低服务器…...
汽车免拆诊断案例 | 保时捷车发动机偶发熄火故障 2 例
案例1 2008款保时捷卡宴车行驶中发动机偶发熄火 故障现象 一辆2008款保时捷卡宴车,搭载4.8 L 自然吸气发动机,累计行驶里程约为21万km。车主反映,该车行驶中发动机偶发熄火;重新起动,发动机能够起动着机ÿ…...
mongodb【实用教程】
MongoDB 是一个开源的文档型数据库管理系统 下载安装 Windows 系统 https://blog.csdn.net/weixin_41192489/article/details/126777309 GUI工具 【推荐】MongoDB Compass https://www.mongodb.com/zh-cn/docs/compass/current/ Robo 3T https://blog.csdn.net/weixin_4119248…...
Javaweb后端数据库多表关系一对多,外键,一对一
多表关系 一对多 多的表里,要有一表里的主键 外键 多的表上,添加外键 一对一 多对多 案例...
React(10)
项目实践--创建项目 在store的modules中创建相关的子仓库暴露到仓库index文件中 导入creatSlice和axios 创建仓库 和数据的异步修改方法 // 编写store // 导入createSlice和axios import { createSlice } from "reduxjs/toolkit"; import axios from "axios&…...
JAVA实战开源项目:靓车汽车销售网站(Vue+SpringBoot) 附源码
本文项目编号 T 093 ,文末自助获取源码 \color{red}{T093,文末自助获取源码} T093,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...
【大语言模型】【整合版】DeepSeek 模型提示词学习笔记(散装的可以看我之前的学习笔记,这里只是归纳与总结了一下思路,内容和之前发的差不多)
以下是个人笔记的正文内容: 原文在FlowUs知识库上,如下截图。里面内容和这里一样,知识排版好看一点 一、什么是 DeepSeek 1. DeepSeek 简介 DeepSeek 是一家专注于通用人工智能(AGI)的中国科技公司,主攻大模型研发与…...
网络安全扫描--基础篇
前言 1、了解互联网安全领域中日趋重要的扫描技术 2、了解在不同网络场景下扫描技术手段 3、熟悉linux下系统内核防护策略并能大件一个有效的系统防护体系 4、增强工作安全意识,并能有效的实践于工作场景中 目录 1、熟悉主机扫描工具(fping,…...
Python网络安全脚本
🍅 点击文末小卡片 ,免费获取网络安全全套资料,资料在手,涨薪更快 前言 睡不着,那就起来学习其实base64模块很早之前用过今天做爬虫的时候有个URL需要用它来编码一下 所以百度又学了一下遇到最大的问题就是python3和p…...
ElasticSearch查询指南:从青铜到王者的骚操作
ElasticSearch查询指南:从青铜到王者的骚操作 本文来源于笔者的CSDN原创,由于掘金>已经去掉了转载功能,所以只好重新上传,以下图片依然保持最初发布的水印(如CSDN水印)。(以后属于本人原创均…...
四、详细解释:网络与连接操作命令
1. ping – 测试网络连通性 用途:检查与目标主机之间的网络连接是否通畅。 语法: ping [选项] 目标IP或域名常用选项: -c 次数:指定发送数据包的次数(默认无限次,需手动 CtrlC 终止)。-i 秒数&…...
前端关于Cursor编辑器的了解与深度使用及对工作的便利
1. 什么是 Cursor 编辑器? Cursor 是一款基于 AI 的现代代码编辑器,类似于 VS Code,但内置了强大的 AI 功能。它的核心目标是帮助开发者更快、更智能地编写代码。 主要特点: AI 驱动的代码补全:提供上下文相关的智能代码建议。代码生成与修复:通过自然语言描述生成代码…...
Java Junit框架
JUnit 是一个广泛使用的 Java 单元测试框架,用于编写和运行可重复的测试。它是 xUnit 家族的一部分,专门为 Java 语言设计。JUnit 的主要目标是帮助开发者编写可维护的测试代码,确保代码的正确性和稳定性。 JUnit 的主要特点 注解驱动&…...
高级自动化测试常见面试题(Web、App、接口)
一、Web自动化测试 1.Selenium中hidden或者是display = none的元素是否可以定位到? 不能,可以写JavaScript将标签中的hidden先改为0,再定位元素 2.Selenium中如何保证操作元素的成功率?也就是说如何保证我点击的元素一定是可以…...
京准电钟解读:为何不能用网络上的NTP时间源服务器
京准电钟解读:为何不能用网络上的NTP时间源服务器 京准电钟解读:为何不能用网络上的NTP时间源服务器 通常是因为以下几个方面的原因: 安全性问题: NTP服务器可能被黑客操纵或成为攻击的目标,如果服务器被攻破&…...
Android OpenGLES2.0开发(十一):渲染YUV
人生如逆旅,我亦是行人 Android OpenGLES开发:EGL环境搭建Android OpenGLES2.0开发(一):艰难的开始Android OpenGLES2.0开发(二):环境搭建Android OpenGLES2.0开发(三&am…...
7种内外网数据交换方案全解析 哪种安全、高效、合规?
内外网数据交换方案主要解决了企业跨网络数据传输中的安全、效率与合规性问题。通过采用先进的加密技术、高效的数据传输协议以及严格的审批和审计机制,该方案确保了数据在内外网之间的安全交换,同时提高了传输效率,并满足了企业对数据合规性…...
详解:事务注解 @Transactional
创作内容丰富的干货文章很费心力,感谢点过此文章的读者,点一个关注鼓励一下作者,激励他分享更多的精彩好文,谢谢大家! Transactional 是 Spring Framework 中常用的注解之一,它可以被用于管理事务。通过使…...
2025最新Flask学习笔记(对照Django做解析)
前言:如果还没学Django的同学,可以看Django 教程 | 菜鸟教程,也可以忽略下文所提及的Django内容;另外,由于我们接手的项目大多都是前后端分离的项目,所以本文会跳过对模板的介绍,感兴趣的朋友可…...
大模型面试问题准备
1. BERT的多头注意力为什么需要多头? 为了捕捉不同子空间的语义信息,每个头关注不同的方面,增强模型的表达能力 2. 什么是softmax上下溢出问题? 问题描述: 上溢出:ye^x中,如果x取非常大的正数…...
FFmpeg 命令行全解析:高效音视频处理从入门到精通
FFmpeg FFmpeg 是一款开源的多媒体处理工具集,支持音视频编解码、格式转换、流媒体处理等全链路操作。核心功能与工具: 多媒体全链路支持 支持 1000+ 音视频编解码格式(如 H.264、HEVC、AV1)和协议(RTMP、RTSP、HLS),覆盖录制、转码、流化等全流程。提供三大核心工具: …...
在使用LomBok时编译器弹出java: 错误: 不支持发行版本 5该怎么解决的四种方案
你遇到的错误 java: 错误: 不支持发行版本 5 表明你的代码正在尝试使用 Java 5 或更早版本的编译器,而这些版本已经不再受支持,并且可能与你当前使用的 JDK 版本不兼容。以下是解决此问题的步骤: 1. 检查项目语言级别 确保你的项目配置为使…...
【数据结构】(12) 反射、枚举、lambda 表达式
一、反射 1、反射机制定义及作用 反射是允许程序在运行时检查和操作类、方法、属性等的机制,能够动态地获取信息、调用方法等。换句话说,在编写程序时,不需要知道要操作的类的具体信息,而是在程序运行时获取和使用。 2、反射机制…...
在VSCode中安装jupyter跑.ipynb格式文件
个人用vs用的较多,不习惯在浏览器单独打开jupyter,看着不舒服,直接上教程。 1、在你的环境中pip install ipykernel 2、在vscode的插件中安装jupyter扩展 3、安装扩展后,打开一个ipynb文件,并且在页面右上角配置内核 …...
WordPress网站502错误全面排查与解决指南
502 Bad Gateway错误是WordPress站长最常遇到的服务器问题之一,它意味着服务器作为网关或代理时,未能从上游服务器获取有效响应。针对WP可能出现的502问题,本文提供一些基础到进阶的解决方案供大家参考:) 一、502错误的本质和核心诱因 502错误属于HTTP状态码中的5xx系列,…...
锂电池保护板测试仪:电池安全的守护者与创新驱动力
在新能源产业蓬勃发展的今天,锂电池以其高能量密度、长循环寿命和环保特性,成为电动汽车、无人机、便携式电子设备等领域不可或缺的能量来源。然而,锂电池的安全性和稳定性一直是行业关注的焦点。为了确保锂电池在各种应用场景下的可靠运行&a…...
flowable-ui 的会签功能实现
场景:在进行智慧保时通开发时,有个协作合同入围功能,这个功能的流程图里有个评审小组,这个评审小组就需要进行会签操作,会签完成后,需要依据是否有不通过的情况选择下一步走的流程 思考步骤: 首…...
Python学习第十七天之PyTorch保姆级安装
PyTorch安装与部署 一、准备工作二、pytorch介绍三、CPU版本pytorch安装1. 创建虚拟环境2. 删除虚拟环境1. 通过环境名称删除2. 通过环境路径删除 3. 配置镜像源4. 安装pytorch1. 首先激活环境变量2. 进入pytorch官网,找到安装指令 5. 验证pytorch是否安装成功 四、…...