Java开发中的设计模式之观察者模式详细讲解
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了对象之间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都会自动收到通知并更新。这种模式在Java开发中非常常见,尤其是在事件驱动的编程场景中,如GUI应用、网络编程等。本文将详细讲解观察者模式的结构、使用场景,并结合代码示例进行说明。
观察者模式的角色
观察者模式包含以下几个核心角色:
-
Subject(主题)
也被称为Observable(可观察者),它是观察者模式的核心对象,表示被观察的实体。Subject负责维护一个观察者列表,并在状态改变时通知所有观察者。 -
Observer(观察者)
观察者是接收Subject状态变化通知的对象。它通常定义一个更新方法,当Subject状态变化时,Observer会执行相应的操作。 -
ConcreteSubject(具体主题)
Subject的具体实现类,负责实现观察者管理(如添加、移除观察者)和通知逻辑。 -
ConcreteObserver(具体观察者)
Observer的具体实现类,定义了收到通知后需要执行的具体行为。
使用场景
观察者模式适用于以下场景:
- 状态变化联动:当一个对象的状态变化需要同时触发其他对象的更新,且不知道具体有多少对象需要响应时。
- 松耦合需求:当一个对象需要通知其他对象,但不希望这些对象之间存在紧耦合关系时。
- 事件驱动系统:在GUI编程(如按钮点击事件监听)、网络通信(消息推送)等场景中,观察者模式是实现事件处理的常用方式。
具体示例场景
- GUI事件监听:在Java的Swing或AWT中,按钮点击后需要通知界面更新。
- 消息订阅系统:用户订阅某主题(如新闻推送),当有新消息时,所有订阅者收到通知。
- 数据监控:实时监控系统,当数据超出阈值时,通知相关模块采取行动。
代码示例
下面是一个简单的Java实现,展示了观察者模式的基本结构和工作原理。
1. 定义Observer接口
public interface Observer {void update(String message); // 观察者收到通知时执行的更新方法
}
2. 定义Subject接口
import java.util.ArrayList;
import java.util.List;public interface Subject {void registerObserver(Observer observer); // 注册观察者void removeObserver(Observer observer); // 移除观察者void notifyObservers(); // 通知所有观察者
}
3. 实现ConcreteSubject
public class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>(); // 存储观察者列表private String message; // Subject的状态(消息)// 设置消息并触发通知public void setMessage(String message) {this.message = message;notifyObservers();}@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(message); // 通知每个观察者}}
}
4. 实现ConcreteObserver
public class ConcreteObserver implements Observer {private String name; // 观察者名称,用于区分不同观察者public ConcreteObserver(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + " received message: " + message); // 收到通知后的行为}
}
5. 测试观察者模式
public class ObserverPatternDemo {public static void main(String[] args) {// 创建主题ConcreteSubject subject = new ConcreteSubject();// 创建观察者Observer observer1 = new ConcreteObserver("Observer 1");Observer observer2 = new ConcreteObserver("Observer 2");// 注册观察者subject.registerObserver(observer1);subject.registerObserver(observer2);// 改变状态,触发通知subject.setMessage("Hello Observers!");// 移除一个观察者subject.removeObserver(observer2);// 再次改变状态,验证效果subject.setMessage("Only Observer 1 should receive this.");}
}
运行结果
Observer 1 received message: Hello Observers!
Observer 2 received message: Hello Observers!
Observer 1 received message: Only Observer 1 should receive this.
代码解释
-
结构设计
Subject接口定义了管理观察者的方法,ConcreteSubject实现了这些方法并维护了观察者列表。Observer接口定义了更新行为,ConcreteObserver实现了具体的响应逻辑。
-
运行流程
- 测试代码中,首先创建了一个主题(
ConcreteSubject)和两个观察者(ConcreteObserver)。 - 通过
registerObserver将观察者注册到主题中。 - 调用
setMessage改变主题状态,触发notifyObservers,所有观察者收到通知并打印消息。 - 移除一个观察者后,再次改变状态,只有剩余的观察者收到通知。
- 测试代码中,首先创建了一个主题(
-
松耦合特性
ConcreteSubject只知道Observer接口,而不关心具体实现类。这种设计降低了对象之间的依赖性。
观察者模式的优缺点
优点
- 松耦合:主题和观察者之间通过接口交互,降低了耦合度。
- 动态扩展:可以在运行时动态添加或移除观察者,增强灵活性。
- 广泛适用:适用于多种场景,如事件处理、发布-订阅系统等。
缺点
- 性能问题:观察者数量过多时,通知过程可能变慢。
- 通知顺序无保障:无法保证观察者被通知的顺序。
- 内存泄漏风险:如果观察者未正确移除,可能导致内存泄漏。
Java中的实际应用
在Java标准库中,观察者模式被广泛使用:
- java.util.Observable 和 java.util.Observer
Java提供了内置的观察者模式支持(现已标记为过时,但仍可参考)。Observable类相当于Subject,Observer接口用于定义观察者。 - 事件监听器
在Swing或JavaFX中,按钮的ActionListener就是观察者模式的典型应用。按钮状态改变时,注册的监听器会被通知。 - Spring框架
Spring的事件机制(如ApplicationEvent和ApplicationListener)也基于观察者模式,用于模块间通信。
总结
观察者模式是一种强大而灵活的设计模式,通过定义一对多的依赖关系,实现了对象之间的松耦合通信。它在Java开发中有着广泛的应用,尤其是在事件驱动的场景下。通过上述代码示例和分析,我们可以看到观察者模式如何在状态变化时通知相关对象,并保持系统的可扩展性和可维护性。在实际开发中,合理使用观察者模式可以显著提高代码的模块化程度。
相关文章:
Java开发中的设计模式之观察者模式详细讲解
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了对象之间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都会自动收到通知并更新。这种模式在Java开发中非常常见,尤其是在事件驱…...
基于SpringAI Alibaba实现RAG架构的深度解析与实践指南
一、RAG技术概述 1.1 什么是RAG技术 RAG(Retrieval-Augmented Generation)检索增强生成是一种将信息检索技术与生成式AI相结合的创新架构。它通过以下方式实现智能化内容生成: 知识检索阶段:从结构化/非结构化数据源中检索相关…...
卷积神经网络(CNN)详解
文章目录 引言1.卷积神经网络(CNN)的诞生背景2.卷积神经网络(CNN)介绍2.1 什么是卷积神经网络?2.2 卷积神经网络(CNN)的基本特征2.2.1 局部感知(Local Connectivity)2.2.…...
element-plus添加暗黑模式
main.ts文件 //引入暗黑模式样式 import "element-plus/theme-chalk/dark/css-vars.css"; style.scss文件 // 设置默认主题色 :root {--base-menu-min-width: 80px;--el-color-primary-light-5: green !important;--route--view--background-color: #fff !import…...
【SF顺丰】顺丰开放平台API对接(注册、API测试篇)
1.注册开发者账号 注册地址:顺丰企业账户中心 2.登录开发平台 登录地址:顺丰开放平台 3.开发者对接 点击开发者对接 4.创建开发对接应用 开发者应用中“新建应用”创建应用,最多创建应用限制数量5个 注意:需要先复制保存生产校验…...
VisualSVN过期后的解决方法
作为一款不错的源代码管理软件,svn还是有很多公司使用的。在vs中使用svn,大家一般用的都是VisualSVN插件。在30天试用期过后,它就不能被免费使用了。下面给大家讲如何免费延长过期时间(自定义天数,可以设定一个很大的值…...
代码随想录算法训练营第二十一天
LeetCode题目: 93. 复原 IP 地址78. 子集90. 子集 II2364. 统计坏数对的数目 其他: 今日总结 往期打卡 93. 复原 IP 地址 跳转: 93. 复原 IP 地址 学习: 代码随想录公开讲解 问题: 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能…...
21. git apply
基本概述 git apply 的作用是:应用补丁文件 基本用法 1.命令格式 git apply [选项] <补丁文件>2.应用补丁 git apply patchfile.patch将补丁应用到工作目录,但不会自动添加到暂存区(需手动 git add) 常用选项 1.检查…...
DeepSeek智能时空数据分析(二):3秒对话式搞定“等时圈”绘制
序言:时空数据分析很有用,但是GIS/时空数据库技术门槛太高 时空数据分析在优化业务运营中至关重要,然而,三大挑战仍制约其发展:技术门槛高,需融合GIS理论、SQL开发与时空数据库等多领域知识;空…...
STM32学习2
一、OLED 1.1 OLED介绍 OLED(Organic Light Emitting Diode):有机发光二极管 OLED显示屏:性能优异的新型显示屏,具有功耗低、相应速度快、宽视角、轻薄柔韧等特点 0.96寸OLED模块:小巧玲珑、占用接口少…...
数据处理: 亲和聚类
Affinity Propagation(亲和传播)是一种基于"消息传递"概念的聚类算法,由Brendan Frey和Delbert Dueck于2007年提出。与K-Means等需要预先指定簇数量的算法不同,Affinity Propagation能够自动确定最佳簇的数量࿰…...
LabVIEW液压系统远程监控与故障诊断
开发了一种基于LabVIEW的远程液压系统监控解决方案,通过先进的数据采集与分析技术,有效提升工程机械的运作效率和故障响应速度。该系统结合现场硬件设备和远程监控软件,实现了液压系统状态的实时检测和故障诊断,极大地提升了维护效…...
Idea中实用设置和插件
目录 一、Idea使用插件 1.Fitten Code智能提示 2.MyBatisCodeHelperPro 3.HighlightBracketPair 4.Rainbow Brackets Lite 5.GitToolBox(存在付费) 6.MavenHelperPro 7.Search In Repository 8.VisualGC(存在付费) 9.vo2dto 10.Key Promoter X 11.CodeGlance…...
安卓处理登录权限问题
在安卓应用中实现登录权限控制,需确保用户登录后才能访问特定功能。以下是分步骤的解决方案: 1. 保存和检查登录状态 使用安全存储保存登录凭证: 推荐使用 EncryptedSharedPreferences 存储敏感信息(如Token、用户ID)…...
Java写数据结构:栈
1.概念: 一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。 压栈:栈的插…...
使用Unity Cache Server提高效率
2021年1月20日19:04:28 1 简介 Unity Cache Server,翻译过来就是Unity缓存服务器 1.1 缓存服务器の官方介绍 Unity 有一个完全自动的资源管线。每当修改 .psd 或 .fbx 文件等源资源时,Unity 都会检测到更改并自动将其重新导入。随后,Unity 以内部格式存储从文件导入的数…...
29个常见的Terraform 面试问题
问题 1:假设您使用 Terraform 创建了一个 EC2 实例,创建完成后,您从状态文件中删除了该条目,那么运行 Terraform Apply 命令时会发生什么? 由于我们已从该状态文件中删除了该条目,因此 Terraform 将不再管…...
机器学习-08-推荐算法-案例
总结 本系列是机器学习课程的系列课程,主要介绍机器学习中关联规则 参考 机器学习(三):Apriori算法(算法精讲) Apriori 算法 理论 重点 MovieLens:一个常用的电影推荐系统领域的数据集 23张图&#x…...
LLM中的N-Gram、TF-IDF和Word embedding
文章目录 1. N-Gram和TF-IDF:通俗易懂的解析1.1 N-Gram:让AI学会"猜词"的技术1.1.1 基本概念1.1.2 工作原理1.1.3 常见类型1.1.4 应用场景1.1.5 优缺点 1.2 TF-IDF:衡量词语重要性的尺子1.2.1 基本概念1.2.2 计算公式1.2.3 为什么需…...
uniapp APP端 DOM生成图片保存到相册
<template> <view class"container" style"padding-bottom: 30rpx;"> <view class"hdbg pr w100 " style"height: 150rpx;"> <top-bar content分享 Back"Back"></top-b…...
Office文件内容提取 | 获取Word文件内容 |Javascript提取PDF文字内容 |PPT文档文字内容提取
关于Office系列文件文字内容的提取 本文主要通过接口的方式获取Office文件和PDF、OFD文件的文字内容。适用于需要获取Word、OFD、PDF、PPT等文件内容的提取实现。例如在线文字统计以及论文文字内容的提取。 一、提取Word及WPS文档的文字内容。 支持以下文件格式: …...
算法——背包问题(分类)
背包问题(Knapsack Problem)是一类经典的组合优化问题,广泛应用于资源分配、投资决策、货物装载等领域。根据约束条件和问题设定的不同,背包问题主要分为以下几种类型: 1. 0-1 背包问题(0-1 Knapsack Probl…...
HXBC编译相关错误
0、Keil MDK报错:Browse information of one or more files is not available----解决方法: 1、使用cubemax生成的工程中,某些引脚自定义了的,是在main.h中,要记得移植。 注意:cubemax生成的spi.c后,在移植的时候,注意hal_driver下面要对应增加hal_stm32H7xxxspi.c …...
Windows 环境下 Apache 配置 WebSocket 支持
目录 前言1. 基本知识2. 实战前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 爬虫神器,无代码爬取,就来:bright.cn 原先写过apache的http配置:Apache httpd-vhosts.conf 配置详解(附Demo) 1. 基本知识 🔁 WebSocket 是 HTTP 的升级协议 客户…...
运维概述(linux 系统)
1、运维的基本概念 2、企业的运行模式 3、计算机硬件 运维概述 运维岗位的定义 在技术人员(写代码的)之间,一致对运维有一个开玩笑的认知:运维就是修电脑的、装网线的、背锅的岗位。 IT运维管理是指为了保障企业IT系统及网络…...
C语言 数据结构 【堆】动态模拟实现,堆排序,TOP-K问题
引言 堆的各个接口的实现(以代码注释为主),实现堆排序,解决经典问题:TOP-K问题 一、堆的概念与结构 堆 具有以下性质 • 堆中某个结点的值总是不大于或不小于其父结点的值; • 堆总是一棵完全二叉树。 二…...
MFC文件-写MP4
下载本文件 本文件将创作MP4视频文件代码整合到两个文件中(Mp4Writer.h和Mp4Writer.cpp),将IYUV视频流编码为H264,PCM音频流编码为AAC,写入MP4文件。本文件仅适用于MFC程序。 使用方法 1.创建MFC项目。 2.将Mp4Writer.h和Mp4Wri…...
8.观察者模式:思考与解读
原文地址:观察者模式:思考与解读 更多内容请关注:7.深入思考与解读设计模式 引言 在开发软件时,系统的某些状态可能会发生变化,而你希望这些变化能够自动通知到依赖它们的其他模块。你是否曾经遇到过,系统中某个对象…...
CMake execute_process用法详解
execute_process 是 CMake 中的一个命令,用于在 CMake 配置阶段(即运行 cmake 命令时)执行外部进程。它与 add_custom_command 或 add_custom_target 不同,后者是在构建阶段(如 make 或 ninja)执行命令。ex…...
模型加载常见问题
safetensors_rust.SafetensorError: Error while deserializing header: HeaderTooLarge 问题代码: model AutoModelForVision2Seq.from_pretrained( "/data-nvme/yang/Qwen2.5-VL-32B-Instruct", trust_remote_codeTrue, torch_dtypetorc…...
