观察者模式-对象间的联动
有个商城小程序,用户希望当有新品上市的时候能通知他们。这样用户就可以不要时刻盯着小程序了。在这个场景中,用户向小程序订阅了一个服务——发送新品短信。小程序在有新品上线时负责向订阅客户发出这个消息。
这就是发布-订阅模式,也称观察者模式。
1 观察者模式
是使用频率最高的设计模式之一。定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并自动更新。

图 观察者模式UML
Subject,目标类。是指被观察的对象,在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供了一系列方法来增加和删除观察者对象,同时定义了通知方法notify(),目标类可以是接口,也可以是抽象或具体类。
ConcreteSubject,具体目标。是目标类的子类,通常包含有经常发生改变的数据。当它当状态发生改变时,向其各个观察者发出通知。同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有)。如果无须扩展目标类,则具体目标类可以省略。
Observer,观察者。观察者将对观察目标的改变做出反应。观察者一般定义为接口。该接口声明了更新数据的方法update()。
ConcreteObserver,具体观察者。实现了Observer中声明的update()方法。通常在实现时,可以调用具体目标类的attach()方法将自己添加到目标类的集合或通过detach()方法将自己从目标类的集合中删除。
public interface Observer {void update(String message);
}public class MessageSubject {private final List<Observer> observerList = new ArrayList<>();public void attach(Observer observer) {this.observerList.add(observer);}public void detach(Observer observer) {this.observerList.remove(observer);}public void notifyObservers(String message) {for (Observer observer : observerList) {observer.update(message);}}}public class AppletMessageSubject extends MessageSubject {@Overridepublic void notifyObservers(String message) {super.notifyObservers(message);System.out.println("小程序平台日志记录,消息发送成功:" + message);}
}public class ApiObserver implements Observer{@Overridepublic void update(String message) {System.out.println("商品推送开始:" + message);}}public class UserObserver implements Observer{@Overridepublic void update(String message) {System.out.println("好的。我知道了,我准备购买:" + message);}
}public class ShopWeb {public static void main(String[] args) {MessageSubject subject = new AppletMessageSubject();Observer userObserver = new UserObserver();Observer apiObserver = new ApiObserver();subject.attach(userObserver);subject.attach(apiObserver);subject.notifyObservers("IPhone 15");subject.notifyObservers("Mate 16");}}//好的。我知道了,我准备购买:IPhone 15
//商品推送开始:IPhone 15
//小程序平台日志记录,消息发送成功:IPhone 15
//好的。我知道了,我准备购买:Mate 16
//商品推送开始:Mate 16
//小程序平台日志记录,消息发送成功:Mate 16
1.1 JDK 对观察者模式的支持
在JDK的java.util包中,提供了Observable类以及Observer接口,它们构成了JDK 对观察者模式的支持。

图 Observable的域与方法

图 Observer 接口
需求:求职者订阅了某boss招聘软件职位发布信息,当有新的职位发布时,会通知给求职者。求职者收到信息后,投递简历。
public class BossObservable extends Observable {@Overridepublic void notifyObservers(Object arg) {super.setChanged();super.notifyObservers(arg);System.out.println("记录日志,职位信息推送成功:" + arg);}
}public class EmployeeObserver implements Observer {private String name;public EmployeeObserver(String name) {this.name = name;}@Overridepublic void update(Observable o, Object arg) {System.out.println(name + "。我钟意这个岗位:" + arg);}}public class Market {public static void main(String[] args) {Observable bossJob = new BossObservable();Observer employee1 = new EmployeeObserver("小李");Observer employee2 = new EmployeeObserver("小吴");bossJob.addObserver(employee1);bossJob.addObserver(employee2);bossJob.notifyObservers("Java 开发");bossJob.notifyObservers("全栈开发");}}//小吴。我钟意这个岗位:Java 开发
//小李。我钟意这个岗位:Java 开发
//记录日志,职位信息推送成功:Java 开发
//小吴。我钟意这个岗位:全栈开发
//小李。我钟意这个岗位:全栈开发
//记录日志,职位信息推送成功:全栈开发
2 优缺点
优点:
1)在观察目标和观察者之间建立一个抽象的耦合。观察目标只需维持一个抽象观察者集合,无须了解其具体观察者。
2)观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知。
缺点:
1)如果一个观察目标对象有许多观察者,将所有观察者都通知到会花费很多时间。
2)如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统奔溃。
3 适用场景
1)一个对象的改变将导致一个或多个其他对象也发生改变,而并不知道具体有多少对象及具体的对象。
2)需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象…可以使用观察者模式创建一种链式触发机制。
相关文章:
观察者模式-对象间的联动
有个商城小程序,用户希望当有新品上市的时候能通知他们。这样用户就可以不要时刻盯着小程序了。在这个场景中,用户向小程序订阅了一个服务——发送新品短信。小程序在有新品上线时负责向订阅客户发出这个消息。 这就是发布-订阅模式,也称观察…...
Webpack十大缺点:当过度工程化遇上简单的静态页面
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…...
新手指南|如何快速参与Moonbeam Ignite
Moonbeam Ignite是社区熟悉的有奖链上交互活动,将有300万枚GLMR作为生态激励注入Moonbeam生态系统,体验MoonbeamMoonbeam生态的应用即可获取相应Token奖励。Beamex/Beamswap、Moonwell和Gamma作为首批参与Moonbeam Ignite的三家项目方,将在活…...
VR航天科普主题公园模拟太空舱体验馆vr航天模拟体验设备
VR航天航空体验馆巡展是一项非常受欢迎的展览活动,可以让公众在现场体验到航天飞行的乐趣。 普乐蛙VR展览组织者会设计一个航天航空主题的VR体验馆,并在馆内设置各种航天航空相关的展示内容,如太空舱、火箭发射、星际航行等。 其次࿰…...
Spring Boot OAuth 2.0整合详解
目录 一、Spring Boot 2.x 示例 1、初始化设置 2、设置重定向URI 3、配置 application.yml 4、启动应用程序 二、Spring Boot 2.x 属性映射 二、CommonOAuth2Provider 三、配置自定义提供者(Provider)属性 四、覆盖 Spring Boot 2.x 的自动配置…...
安装visual studio报错“无法安装msodbcsql“
在安装visual studio2022时安装完成后提示无法安装msodbcsql, 查看日志文件详细信息提示:指定账户已存在。 未能安装包“msodbcsql,version17.2.30929.1,chipx64,languagezh-CN”。 搜索 URL https://aka.ms/VSSetupErrorReports?qPackageIdmsodbcsql;PackageActi…...
webGL编程指南 第三章 矩阵平移三角形.translatedTriangle_Matrix
我会持续更新关于wegl的编程指南中的代码。 当前的代码不会使用书中的缩写,每一步都是会展开写。希望能给后来学习的一些帮助 git代码地址 :git 接着 上一节 中 我们使用矩阵进行旋转,这次我们使用矩阵实现位移 <!DOCTYPE html> <…...
修改echarts的tooltip样式 折线图如何配置阴影并实现渐变色和自适应
图片展示 一、引入echarts 这里不用多解释 vue里使用 import echarts from “echarts”; html页面引用js文件或用script标签引用 二、定义一个具有宽高的dom div <div id"echart-broken" style"width:400px;height: 200px;"></div>三、定义…...
[论文笔记] SurroundOcc: Multi-Camera 3D Occupancy Prediction for Autonomous Driving
Wei, Yi, et al. “Surroundocc: Multi-camera 3d occupancy prediction for autonomous driving.” Proceedings of the IEEE/CVF International Conference on Computer Vision. 2023. 重点记录 将占用网格应用到多个相机构成的3D空间中; 使用BEVFormer中的方法获取3D特征, …...
辅助驾驶功能开发-功能对标篇(16)-NOA 城市辅助系统-毫末智行
1.横向对标参数 厂商毫末智行车型魏牌摩卡DHT-PHEV上市时间发布:2022年8月30日 上市:2022年底前方案12V5R2L+1DMS摄像头前视摄像头*3【800W】侧视摄像头*4后视摄像头*1【800W】环视摄像头*4DMS摄像头*1雷达毫米波雷达*54D毫米波雷达/超声波雷达*12激光雷达*2【速腾聚创 M1,1…...
H3C的IRF堆叠互联关系说明
H3C IRF堆叠互联说明48口交换机连接方式IRF Port 两台设备第一台的51口 第二台的51口irf-port 1/2 port group interface ten-gigabitethernet 1/0/51 port group interface ten-gigabitethernet 1/0/52第一台的52口第二台的52口irf-port 2/1 port group interface ten-gigabi…...
货物摆放(蓝桥杯)
货物摆放 题目描述 小蓝有一个超大的仓库,可以摆放很多货物。 现在,小蓝有 n 箱货物要摆放在仓库,每箱货物都是规则的正方体。小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。 小蓝希望所有的…...
3782: 【C3】【穷举】弹珠游戏
目录 题目描述 输入 输出 样例输入 样例输出 题目描述 游戏的内容是:在一个 n*n 的矩阵里,有若干个敌人,你的弹珠可以摧毁敌人,但只能攻击你所在的行、列里的所有敌人,然后你就可以获得他们的分数之和࿰…...
leetcode 5
leetcode 5 题目是通过枚举字符串,然后判断是否子字符串满足回文。 引用传递和值传递相比,引用传递可以减少内存空间。提高代码运行效率。 https://www.cnblogs.com/yanlingyin/archive/2011/12/07/2278961.html...
centos中nacos设置开机自启动
以下实践亲测有效! 1、在以下目录编辑新建nacos.service文件 vim /lib/systemd/system/nacos.service [Unit] Descriptionnacos Afternetwork.target [Service] Typeforking ExecStart/usr/local/nacos/bin/startup.sh -m standalone ExecReload/usr/local/nacos/b…...
双指针——移动零
一,题目要求: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0…...
WPF中在MVVM模式下实现导航功能
WPF中在MVVM模式下实现导航功能 一、利用TabControl 使用场景:项目小,不用考虑内存开销的问题。 实现方式1-手动指定ViewModel 分别定义3个UserControl作为View用于演示 <UserControl...><Grid><StackPanel Orientation"Vertic…...
SpringBoot面试题2:SpringBoot与SpringCloud 区别?SpringBoot和Spring、SpringMVC的区别
该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:SpringBoot与SpringCloud 区别? Spring Boot 和 Spring Cloud 是 Spring 生态系统中的两个关键组件,它们有以下区别: 定位:Spring Boot 用于简…...
Practical Deep Raw Image Denoisingon Mobile Devices
Abstract 近年来,基于深度学习的图像去噪方法得到了广泛的研究,并在许多公共基准数据集中盛行。然而,最先进的网络计算成本太高,无法直接应用于移动设备。在这项工作中,我们提出了一种轻量级、高效的基于神经网络的原…...
如何在Android项目中制作和使用三方包(jar文件)
文章目录 1 概念介绍2 制作方法2.1 制作步骤2.2 制作结果3 使用方法3.1 具体步骤3.2 示例代码4 内容总结在项目中为了跨部门协作需要把相关的内容打成包文件,基于这个需求,我们将介绍如何把 代码制作成三方包,这里的三方包是指jar文件。同时也会介绍如何在Android项目中使用…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
