设计模式之 观察者模式
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象(Subject)。当主题对象的状态发生变化时,所有依赖于它的观察者都会得到通知并自动更新。观察者模式的应用可以减少对象之间的耦合度,促进系统的解耦,使得对象间的协作变得更加灵活。
观察者模式特别适用于那些需要在一个对象状态变化时,通知多个对象并进行相应处理的场景。它通常用于事件驱动的系统、模型-视图-控制(MVC)架构、GUI框架等应用中。
一、观察者模式的定义
在观察者模式中,主题对象(Subject)保持对多个观察者对象(Observer)的引用,并在自身状态改变时通知它们。观察者对象通过订
阅主题对象来接收通知,而无需主动去查询主题对象的状态。主题和观察者之间通过一个简单的接口进行通信,使得它们之间的耦合度降低。
二、观察者模式的组成部分
观察者模式主要由以下几个角色组成:
-
Subject(主题/被观察者):
主题对象是观察者模式的核心,它维护一个观察者列表,并定义向观察者发送通知的方法。主题的状态发生变化时,它会通知所有的观察者。
常见的操作有:注册观察者、删除观察者、通知观察者。 -
Observer(观察者):
观察者是需要接收主题通知的对象,它定义了接收通知的接口。当主题对象状态发生变化时,观察者会自动调用该接口来更新自身状态。 -
ConcreteSubject(具体主题):
具体主题类实现了Subject接口,并维护自己的状态。当它的状态变化时,会调用所有注册的观察者的更新方法。 -
ConcreteObserver(具体观察者):
具体观察者类实现了Observer接口,并在接收到通知时更新自己的状态。具体观察者与具体主题密切相关,通常它们的状态依赖于主题的状态。
三、观察者模式的工作原理
观察者模式的工作原理可以总结为以下步骤:
-
注册观察者:观察者对象通过调用主题对象的
attach()
方法注册自己,成为主题的观察者。 -
通知观察者:当主题的状态发生变化时,主题对象调用
notify()
方法,通知所有注册的观察者。 -
观察者更新:观察者对象收到通知后,会调用自身的
update()
方法,根据主题的状态更新自己的状态。 -
取消订阅:如果观察者不再关心主题的状态变化,它可以通过调用主题的
detach()
方法注销自己,不再接收通知。
四、观察者模式的代码示例
假设我们有一个简单的天气预报系统,系统需要通知不同的显示设备(如手机、电脑)更新天气信息。当天气变化时,所有已注册的显示设备都会自动接收到天气更新。
定义观察者接口
public interface Observer {public void update(String weather);
}
定义主题接口
public interface Subject {void attach(Observer observer);void detach(Observer observer);void notifyObservers();
}
具体主题类:WeatherStation(天气站)
public class WeatherStation implements Subject{private List<Observer> observers = new ArrayList<>();private String weather;public void setWeather(String weather) {this.weather = weather;notifyObservers();}@Overridepublic void attach(Observer observer) {observers.add(observer);}@Overridepublic void detach(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(weather);}}
}
具体观察者类:PhoneDisplay(手机显示)
public class PhoneDisplay implements Observer{@Overridepublic void update(String weather) {System.out.println("手机端天气变为"+ weather);}
}
具体观察者类:ComputerDisplay(电脑显示)
public class ComputerDisplay implements Observer{@Overridepublic void update(String weather) {System.out.println("电脑端天气变为"+weather);}
}
客户端代码
public class Client {public static void main(String[] args) {WeatherStation station = new WeatherStation();station.attach(new ComputerDisplay());station.attach(new PhoneDisplay());station.setWeather("晴天");}
}
运行结果

五、观察者模式的优缺点
优点:
-
降低耦合性:观察者模式使得主题和观察者之间的耦合度降低,观察者无需了解主题的内部实现,主题也无需了解每个观察者的具体细节。只通过接口进行通信。
-
支持多种观察者:多个观察者可以同时订阅同一个主题对象,在主题对象状态发生变化时,所有观察者都会被通知并做出响应。
-
增强灵活性:如果主题的状态发生变化,观察者无需主动查询主题,而是通过通知机制自动获取更新。观察者可以随时添加或移除,不影响系统其他部分。
-
扩展性强:如果需要新增新的观察者,只需要创建新的观察者类,并注册到主题中即可,主题对象不需要做任何修改,符合开放封闭原则。
缺点:
-
可能引起性能问题:如果观察者非常多,每当主题状态变化时,都会通知所有观察者。如果观察者处理较慢或者状态更新频繁,可能会导致性能问题。
-
观察者过多时管理困难:如果观察者的数量非常大,管理这些观察者可能变得复杂,特别是在需要追踪哪些观察者已经收到通知时。
-
难以控制通知的顺序:在一些复杂的场景中,可能希望通知观察者的顺序有一定的控制,而观察者模式通常是按照注册顺序发送通知的。
六、观察者模式的应用场景
-
事件处理系统:在事件驱动的系统中,事件的发生通常需要通知多个监听者,如图形界面中的按钮点击、鼠标拖拽等事件。
-
模型-视图-控制(MVC)模式:在MVC架构中,视图(Observer)需要根据模型(Subject)的变化来更新显示。模型的状态变化会通知所有相关的视图进行刷新。
-
通知推送系统:当数据变化时,通知用户的系统,比如邮件通知、即时通讯应用中的消息推送等。
-
股票市场监控:投资者或分析师(观察者)订阅股票(主题)信息,当股票价格发生变化时,系统会自动推送通知给所有订阅者。
相关文章:
设计模式之 观察者模式
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象(Subject)。当主题对象的状态发生变化时,所有依赖于它的观察者都会得到…...
SQLSever显示物理和逻辑 IO活动量的相关信息及显示分析、编译和执行各语句所需的毫秒数。
SQLSever SET STATISTICS IO显示物理和逻辑 IO活动量的相关信息及SET STATISTICS TIME显示分析、编译和执行各语句所需的毫秒数。 1、 SET STATISTICS IO (Transact-SQL) 物理 IO 与访问磁盘上的数据页相关,逻辑 IO 与访问内存中的数据页(数据缓存&…...
CSS3 动画:前端开发的动态美
CSS3 动画:前端开发的动态美 CSS3 动画是现代网页设计中不可或缺的一部分,它为静态的网页元素添加了动态效果,提升了用户体验。本文将深入探讨CSS3动画的基础知识、高级技巧,并展示如何在实际项目中应用这些动画。 CSS3 动画基础 CSS3动画主要通过@keyframes和动画属性(…...
JavaWeb之综合案例
前言 这一节讲一个案例 1. 环境搭建 然后就是把这些数据全部用到sql语句中执行 2.查询所有-后台&前台 我们先写后台代码 2.1 后台 2.2 Dao BrandMapper: 注意因为数据库里面的名称是下划线分割的,我们类里面是驼峰的,所以要映射 …...
基于Spring Boot+Unipp的博物馆预约小程序(协同过滤算法、二维码识别)【原创】
🎈系统亮点:协同过滤算法、二维码识别; 一.系统开发工具与环境搭建 1.系统设计开发工具 后端使用Java编程语言的Spring boot框架 项目架构:B/S架构 运行环境:win10/win11、jdk17 前端: 技术:框…...
使用 Maven 构建一个简单的 Java 项目
Apache Maven 是一个强大的构建自动化工具,主要用于 Java 项目。它简化了构建和管理任何基于 Java 的项目的流程。 本指南将涵盖 Maven 的安装、设置一个简单的 Java 项目以及使用 Maven 运行该项目。 1. 安装 安装 Java 在安装 Maven 之前,需要确保…...
【51单片机】LCD1602液晶显示屏
学习使用的开发板:STC89C52RC/LE52RC 编程软件:Keil5 烧录软件:stc-isp 开发板实图: 文章目录 LCD1602存储结构时序结构 编码 —— 显示字符、数字 LCD1602 LCD1602(Liquid Crystal Display)液晶显示屏是…...
UDP协议
UDP(UserDatagramProtocol)是一个简单的传输层协议,特点:无连接、不可靠、面向数据包、全双工。 报文结构 1.源端口: 源端口号,需要对方回信时选用,不需要时全部置0. 2.目的端口:目…...
阅读 ADiffusion-Based Framework for Multi-Class Anomaly Detection
A Diffusion-Based Framework for Multi-Class Anomaly Detection 我觉得引言部分写的不错,将问题清楚的讲出来了,值得借鉴!! 摘要 基于重建的方法在异常检测方面取得了显著成果。最近流行的扩散模型的卓越图像重建能力引发了研…...
网络云计算】2024第47周-每日【2024/11/21】周考-实操题-RAID6实操解析1
文章目录 1、RAID6配置指南(大致步骤)2、注意事项3、截图和视频 网络云计算】2024第47周-每日【2024/11/21】周考-实操题-RAID6实操 RAID6是一种在存储系统中实现数据冗余和容错的技术,其最多可以容忍两块磁盘同时损坏而不造成数据丢失。RAID…...
ts- declare关键词及vue3报错“Window typeof globalThis”上不存在属性“nextLoading”、`
报错“Window & typeof globalThis”上不存在属性“nextLoading”、 代码环境:vue3、ts 阮一峰讲解 declarets 用法告诉编译器某个类型是存在的 下面的例子是脚本使用浏览器全局对象document。 declare var document; document.title "Hello";上面…...
【STM32】在 STM32 USB 设备库添加新的设备类
说实话,我非常想吐槽 STM32 的 USB device library,总感觉很混乱。 USB Device library architecture 根据架构图: Adding a custom class 如果你想添加新的设备类,必须修改的文件有 usbd_desc.cusbd_conf.cusb_device.c 需要…...
【单点知识】基于PyTorch讲解自动编码器(Autoencoder)
文章目录 0. 前言1. 自动编码器的基本概念1.1 定义1.2 目标1.3 结构 2. PyTorch实现自动编码器2.1 导入必要的库2.2 定义自动编码器模型2.3 加载数据2.4 训练自动编码器 3. 自动编码器的意义4. 自动编码器的应用4.1 图像处理4.2自然语言处理:4.3推荐系统:…...
html+js实现图片的放大缩小等比缩放翻转,自动播放切换,顺逆时针旋转
效果图: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>图片预览</title><sty…...
【蓝桥杯C/C++】翻转游戏:多种实现与解法解析
博客主页: [小ᶻZ࿆] 本文专栏: 蓝桥杯C/C 文章目录 💯题目💯问题分析解法一:减法法解法二:位运算解法解法三:逻辑非解法解法四:条件运算符解法解法五:数组映射法不同解法的比较…...
介绍一下toupper(ch);函数(c基础)
hi , I am 36 适合对象c语言初学者 toupper(ch1); tolower(ch2); 是返回ch的大写或小写的字符但并不改变ch 若传递数字仍返回该数字 格式 #include<ctype.h> char res toupper(ch); 链接扫雷游戏代码分享(c基础)-CSDN博客 hi , I am 36. thanks for your look…...
如何使用Python代码实现给GPU预加热
如何使用Python代码实现给GPU预加热 一、引言二、使用深度学习框架进行预加热2.1 TensorFlow预加热2.2 PyTorch预加热三、使用CUDA进行预加热四、预加热的效果评估与优化五、结论与展望在高性能计算和深度学习领域,GPU(图形处理器)已经成为不可或缺的加速工具。然而,在实际…...
基于 SpringBoot 的作业管理系统【附源码】
基于 SpringBoot 的作业管理系统 效果如下: 系统注册页面 学生管理页面 作业管理页面 作业提交页面 系统管理员主页面 研究背景 随着社会的快速发展,信息技术的广泛应用已经渗透到各个行业。在教育领域,课程作业管理是学校教学活动中的重要…...
LeetCode题解:26.删除有序数组中的重复项【Python题解超详细,双指针法】,知识拓展:原地修改
题目描述 给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k &…...
docker 容器运行Ruoyi-cloud
1,linux系统安装openjdk1.8,mvn,dokcer,node,git 2,拉取代码 1)查看gitee仓库地址 2)创建/app文件夹,进入app目录 mkdir /app cd /app 3)clone代码 4)修改配置文件中nacos地址 # 修改注…...
【Unity How】Unity中如何实现物体的匀速往返移动
直接上代码 using UnityEngine;public class CubeBouncePingPong : MonoBehaviour {[Header("移动参数")][Tooltip("移动速度")]public float moveSpeed 2f; // 控制移动的速度[Tooltip("最大移动距离")]public float maxDistance 5f; // 最大…...
STM32完全学习——系统时钟设置
一、时钟框图的解读 首先我们知道STM32在上电初始化之后使用的是内部的HSI未经过分频直接通过SW供给给系统时钟,由于内部HSI存在较大的误差,因此我们在系统完成上电初始化,之后需要将STM32的时钟切换到外部HSE作为系统时钟,那么我…...
简单理解下基于 Redisson 库的分布式锁机制
目录 简单理解下基于 Redisson 库的分布式锁机制代码流程:方法的调用:具体锁的实现:riderBalance 方法:tryLock 方法(重载):tryLock 方法(核心实现): 简单理解…...
ruoyi框架完成分库分表,按月自动建表功能
前提 这个分库分表功能,按月自动建表,做的比较久了,还没上线,是在ruoyi框架内做的,踩了不少坑,但是已经实现了,就分享一下代码吧 参考 先分享一些参考文章 【若依系列】集成ShardingSphere S…...
数据结构 【单链表练习】
今天来探讨两个练习题要使用的思想为快慢指针。 1、返回链表的中间节点 给你单链表的头结点 head ,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。 整体思路如下图所示: 代码如下: /*** Definition f…...
wsl虚拟机中的dockers容器访问不了物理主机
1 首先保证wsl虚拟机能够访问宿主机IP地址,wsl虚拟机通过vEthernet (WSL)的地址访问,着意味着容器也要通过此IP地址访问物理主机。 2 遇到的问题:wsl虚拟机中安装了docker,用在用到docker容器内的开发环境,但是虚拟机…...
Elasticsearch 开放推理 API 增加了对 IBM watsonx.ai Slate 嵌入模型的支持
作者:来自 Elastic Saikat Sarkar 使用 Elasticsearch 向量数据库构建搜索 AI 体验时如何使用 IBM watsonx™ Slate 文本嵌入。 Elastic 很高兴地宣布,通过集成 IBM watsonx™ Slate 嵌入模型,我们的开放推理 API 功能得以扩展,这…...
【如何用更少的数据作出更好的决策】-gpt生成
如何用更少的数据作出更好的决策 用更少的数据作出更好的决策是一种能力的体现,需要结合有效的方法、严谨的逻辑以及对问题的深刻理解。以下是一些可以帮助你实现这一目标的策略: 明确目标 在收集和分析数据之前,先明确你的决策目标是什么…...
webview4/edgewebbrower学习记录——执行js
webview2可执行js方法:WVBrowser1.ExecuteScript(js, 1003) 参数1为js语句,参数2为命令号,执行完毕,会执行 procedure TBrowserFrame.WVBrowser1ExecuteScriptCompleted(Sender: TObject; aErrorCode: HRESULT; const aResultOb…...
Java文件上传解压
目录结构 工具类 枚举 定义文件类型 public enum FileType {// 未知UNKNOWN,// 压缩文件ZIP, RAR, _7Z, TAR, GZ, TAR_GZ, BZ2, TAR_BZ2,// 位图文件BMP, PNG, JPG, JPEG,// 矢量图文件SVG,// 影音文件AVI, MP4, MP3, AAR, OGG, WAV, WAVE}为了避免文件被修改后缀࿰…...
人工智能(AI)与机器学习(ML)基础知识
目录 1. 人工智能与机器学习的核心概念 什么是人工智能(AI)? 什么是机器学习(ML)? 什么是深度学习(DL)? 2. 机器学习的三大类型 (1)监督式学…...
autoware(2)运行自己的数据集
上一节完成了autoware.ai的安装和编译跑通了demo数据集,本将自己录制的数据包用于测试 1.修改点云地图 将加载点云地图的my_map.launch文件复制并命名为my_map_test.launch, (1)point cloud处替代原来的点云地图为自己的&#…...
HBase Java基础操作
Apache HBase 是一个开源的、分布式的、可扩展的大数据存储系统,它基于 Google 的 Bigtable 模型。使用 Java 操作 HBase 通常需要借助 HBase 提供的 Java API。以下是一个基本的示例,展示了如何在 Java 中连接到 HBase 并执行一些基本的操作,…...
巧用观测云可用性监测(云拨测)
前言 做为系统运维或者开发,很多时候我们需要能够实时感知我们所运维的系统和服务的情况,比如以下的场景: 系统上线前测试:包括功能完整性检查,确保页面元素(如图像、视频、脚本等)都能够正常…...
Chrome离线安装包下载
1、问Chrome的官网:https://www.google.cn/chrome/ 直接下载的是在线安装包,安装需要联网。 2、如果需要在无法联网的设备上安装Chrome,需要在上面的地址后面加上?standalone1。 Chrome离线安装包下载地址:https://www.google.c…...
ceph的RBD管理
0 块设备介绍 Ceph 的块设备(Ceph Block Device, RBD)是其存储服务的一种实现形式,通过 librbd 库或 Linux 内核模块提供块设备支持,所以可以与主流云平台(如 OpenStack)、虚拟化平台(如 KVM&a…...
【数论】莫比乌斯函数及其反演
文章目录 一、介绍二、莫比乌斯函数的算法求解三、例题 在学习之前,先来了解一下常见定义吧(OVO): 常见数论函数分为两种: { 完全积性函数:对于任意 p , q ∈ N ,有 f ( p ⋅ q ) f ( p ) ⋅ …...
低音运行,约克VRF中央空调让居家生活静享安宁
不仅节能省电,约克VRF中央空调还特别注重运行的静音效果,低至17dB超低运行噪音,让你在享受舒适环境的同时,也能拥有宁静的居家氛围。无论是工作、学习还是休息,都不受噪音干扰。...
使用 Ansys LS-DYNA 进行玻璃瓶包装跌落分析
使用 Ansys LS-DYNA 进行玻璃瓶包装跌落分析 玻璃瓶包装跌落分析 使用两个玻璃瓶,其中一个为纸盒包装,用来演示包装效果。 Johnson–Holmquist 损伤模型用于玻璃 (MAT_JOHNSON_HOLMQUIST_CERAMICS)纸箱包装采用各向同性弹性材料模型。瓶子将从 300 毫米…...
Windows系统编程 - 进程遍历
文章目录 前言进程的遍历CreateToolhelp32SnapshotProcess32FirstProcess32Next进程遍历 总结 前言 各位师傅好,我是qmx_07,今天给大家讲解进程遍历的相关知识点 进程的遍历 快照:使用vmware虚拟机的时候,经常需要配置环境服务…...
【电路笔记 TMS320F28335DSP】时钟+看门狗+相关寄存器(功能模块使能、时钟频率配置、看门狗配置)
时钟源和主时钟(SYSCLKOUT) 外部晶振:通常使用外部晶振(如 20 MHz)作为主要时钟源。内部振荡器:还可以选择内部振荡器(INTOSC1 和 INTOSC2),适合无需高精度外部时钟的应…...
gt730是什么显卡?gt730显卡性能参数介绍
NVIDIA GeForce GT 730是一款入门级图形卡,于2014年推出,基于40纳米工艺和GF108图形处理器。尽管它支持DirectX 12,但功能级别仅为11_0,这可能会在新的DirectX 12标题中造成问题。GT 730具有96个着色单元,16个纹理映射…...
Swift内存访问冲突
内存的访问,发生在给变量赋值的时候,或者传递值(给函数)的时候,例如 var one 1//向one的内存区域发起一次写的操作 print("\(one)")//向one的内存区域发起一次读的操作 在 Swift 里,有很多修改…...
2024.6使用 UMLS 集成的基于 CNN 的文本索引增强医学图像检索
Enhancing Medical Image Retrieval with UMLS-Integrated CNN-Based Text Indexing 问题 医疗图像检索中,图像与相关文本的一致性问题,如患者有病症但影像可能无明显异常,影响图像检索系统准确性。传统的基于文本的医学图像检索࿰…...
力扣刷题--21.合并两个有序链表
I am the best !!! 题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1: 输入:l1 [1,2,4], l2 [1,3,4] 输出:[1,1,2,3,4,4] 示例 2…...
Diving into the STM32 HAL-----DAC笔记
根据所使用的系列和封装,STM32微控制器通常只提供一个具有一个或两个专用输出的DAC,除了STM32F3系列中的少数零件编号实现两个DAC,第一个具有两个输出,另一个只有一个输出。STM32G4 系列的一些较新的 MCU 甚至提供多达 5 个独立的…...
每日一题 LCR 078. 合并 K 个升序链表
LCR 078. 合并 K 个升序链表 使用二分法就可以解决 class Solution { public:ListNode* mergeKLists(vector<ListNode*>& lists) {int n lists.size();if(n 0){return nullptr;}ListNode* ans ;ans binMerge(lists,0,n-1);return ans;}ListNode* binMerge(vector…...
如何在分布式环境中实现高可靠性分布式锁
目录 一、简单了解分布式锁 (一)分布式锁:应对分布式环境的同步挑战 (二)分布式锁的实现方式 (三)分布式锁的使用场景 (四)分布式锁需满足的特点 二、Redis 实现分…...
如何利用java爬虫获得淘宝商品评论
在当今数字化时代,数据的价值日益凸显,尤其是对于电商平台而言,商品评论作为用户反馈的重要载体,蕴含着丰富的信息。本文将详细介绍如何利用Java爬虫技术获取淘宝商品评论,包括代码示例和关键步骤解析。 淘宝商品评论的…...
SQLAlchemy,ORM的Python标杆!
嗨,Python的小伙伴们!今天咱们来了解 SQLAlchemy,这可是对象关系映射(ORM)里的超级标杆哦!它就像一座神奇的桥梁,能让我们用 Python 代码轻松地和数据库打交道,不用写复杂的 SQL 语句…...