设计模式-观察者模式(观察者模式的需求衍变过程详解,关于监听的理解)
目录
- 前言
- 概念
- 你有过这样的问题吗?
- 详细介绍
- 原理:
- 应用场景:
- 实现方式:
- 类图
- 代码
- 问题回答
- 监听,为什么叫监听,具体代码是哪
- 观察者模式的需求衍变过程
- 观察者是为什么是行为型
- 总结:
前言
在软件设计中,对象之间的通信是非常常见的情况。然而,当对象之间的通信过于紧密,可能会导致代码的耦合度增加,使得系统难以维护和扩展。为了解决这个问题,观察者模式应运而生。本文将介绍观察者模式的原理、应用场景以及实现方式,并通过图、代码和例子进行详细说明。
概念
观察者模式通过定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,会自动通知所有观察者对象进行相应的更新操作。
你有过这样的问题吗?
- 概念中说“多个观察者对象同时监听某一个主题对象”,什么叫监听,监听是被动的还是主动的?在代码中哪块体现监听了?
- 观察者模式的需求是如何演变的?
- 观察者模式属于行为型,为什么呢?行为型有什么特点吗?
- 观察者模式应用场景有哪些?有什么不足吗?
带着类似的问题,看下面的内容,文章的最后也会对这些问题一一回答
详细介绍
原理:
观察者模式由两个核心角色组成:主题(Subject)和观察者(Observer)。主题对象维护一个观察者列表(有个容器用来放观察者),当主题对象的状态发生变化时,会遍历观察者列表,依次通知每个观察者进行相应的更新操作。观察者对象则通过注册到主题对象上,以接收主题对象的通知。
应用场景:
观察者模式在许多实际应用中都有广泛的应用,例如:
-
消息订阅和发布系统:主题对象充当消息发布者,观察者对象充当消息订阅者。当发布者发布新消息时,订阅者会收到通知并进行相应的处理。
-
GUI开发:主题对象可以是用户界面组件,观察者对象可以是与该组件相关的其他组件。当用户界面组件发生变化时,其他组件可以及时更新自身的状态。
-
股票市场监控系统:主题对象可以是股票市场,观察者对象可以是投资者。当股票市场行情发生变化时,投资者可以及时了解到最新的行情。
实现方式:
类图

代码
下面通过一个简单的示例来演示观察者模式的实现。
- 首先,我们定义主题接口(Subject),包含注册观察者、移除观察者和通知观察者的方法。
public interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}
- 然后,我们定义观察者接口(Observer),包含接收通知并进行更新操作的方法。
public interface Observer {void update();
}
- 接下来,我们实现具体的主题类(ConcreteSubject),并在该类中实现注册观察者、移除观察者和通知观察者的方法。
public class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();@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();}}// 其他业务逻辑...
}
- 最后,我们实现具体的观察者类(ConcreteObserver),并在该类中实现接收通知并进行更新操作的方法。
public class ConcreteObserver implements Observer {@Overridepublic void update() {// 执行更新操作...}
}
通过以上代码,我们可以看到,主题对象和观察者对象之间并没有直接的耦合关系,它们通过接口进行通信,实现了松耦合的对象间通信。
问题回答
监听,为什么叫监听,具体代码是哪
在观察者模式中,观察者对象通过注册(或订阅)的方式来监听某一个主题对象。这个监听的过程在代码中体现在观察者对象注册到主题对象的观察者列表中。
具体地,主题对象通常会提供一些方法,例如attach(observer)和detach(observer),用于观察者对象的注册和注销。当主题对象的状态发生变化时,它会遍历观察者列表,并调用每个观察者对象的相应方法,通知它们状态的变化。
关于为什么称之为"监听",这是因为在观察者模式中,观察者对象并不需要主动去轮询或查询主题对象的状态,而是被动地接收主题对象的通知。观察者对象通过注册到主题对象上,就像是在"监听"主题对象的状态变化。
观察者对象并没有主动去听的动作,但它们被动地接收主题对象的通知,从而实现了对主题对象状态变化的监听。这种被动的接收通知的行为,可以理解为观察者对象在"监听"主题对象。
观察者模式的需求衍变过程
故事背景:
老板回来,前台秘书发通知消息给正在玩的同事们(前提是,同事提前在秘书那“注册”过–“老板来了通知我一下”),收到秘书的通知后,同事们各自采取行动
宏观
最初的通知者和观察者是明确知道对方的存在的,但是在经过一次次的优化后观察者和通知者都不知道对方具体存在只知晓一个接口或者抽象类,这里就是在一对多通知的时候使用这种抽象的好处,不需要知道具体的通知者和观察者。
微观:
1.双向耦合:
开始有三个类:前台秘书类,看股票同事类,客户端,此时的前台秘书类与观察者类相互耦合,前台秘书类要增加观察者、观察者需要前台的的状态。
需要解决的问题是:前台秘书类与观察者类相互耦合。
2.解耦
增加抽象的观察者,增加了看NBA的同事,看股票的同事与看NBA 的同事继承抽象观察者。前台秘书类中与具体的观察者耦合的地方都改成了抽象观察者。存在的问题是:具体的观察者不应该依赖具体的主题,而是需要一个抽象的通知者。如果前台有事来不及通知,那么通知谁来做?前台不想通知某位同事,需要有移除方法进行支持。
3.观察者模式
观察者模式的作用是在解耦合,让耦合的双方都依赖抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
如果观察者是风马牛不相及的类,使用接口更加合适。
观察者模式的不足:
抽象通知者依赖抽象观察者,应该由客户端决定通知谁;并不是每个具体的观察者都是更新方法。
事件与委托的实现
看股票的观察者类、看NBA 观察者类 去掉了父类抽象观察者,并将更新方法名改为自己合适的方法名字。抽象观察者不要了,声明EventHandler委托,在具体的统治者类增加委托事件-update。
观察者是为什么是行为型
观察者模式是一种行为型设计模式,因为它关注的是对象之间的行为和交互,通过定义接口和松耦合的方式实现了对象之间的动态关联。
在观察者模式中,被观察者和观察者之间通过定义接口进行通信,这就意味着它们之间可以有不同的行为。被观察者负责维护观察者的列表,并在状态发生改变时通知观察者。观察者则负责定义在接收到通知时要执行的行为。
观察者模式的行为型特点还体现在它的实现方式上。在观察者模式中,被观察者和观察者之间是松耦合的,它们之间的关联是动态的,可以随时添加或移除观察者。这种灵活性使得观察者模式非常适合在复杂的系统中处理对象之间的行为和交互。
简单一句话总结行为型设计模式特点:
行为型模式的核心,都有一个类,把整个模式要做的事封装在这个类的一个方法里执行。
具体在观察者模式中这个类是ConcreteObserver,具体是其中的构造方法。具体观察者,只管要它要订阅哪个主题,(this.subject=subject.)但是它不管订阅的主题具体做什么事,进而实现了整个设计模式要实现的行为。
总结:
观察者模式通过定义一种一对多的依赖关系,实现了对象之间的松耦合通信。它能够帮助我们构建可维护和可扩展的系统。在实际应用中,我们可以根据具体的需求进行灵活的扩展和定制。希望本文对你理解观察者模式有所帮助。
相关文章:
设计模式-观察者模式(观察者模式的需求衍变过程详解,关于监听的理解)
目录 前言概念你有过这样的问题吗? 详细介绍原理:应用场景: 实现方式:类图代码 问题回答监听,为什么叫监听,具体代码是哪观察者模式的需求衍变过程观察者是为什么是行为型 总结: 前言 在软件设计…...
vue+electron中实现文件下载打开wps预览
下载事件 win.webContents.downloadURL(url) 触发session的will-download事件 win.webContents.session.on(will-download, (event, downloadItem, webContents) > {// 设置文件保存路径// 如果用户没有设置保存路径,Electron将使用默认方式来确定保存路径&am…...
第4章 性能分析中的术语和指标
Linux perf和Intel VTune Profiler工具。 4.1 退休指令与执行指令 考虑到投机执行,CPU执行的指令要不退休指令多。Linux perf使用perf stat -e instruction ./a.exe即可获得退休指令的数量。 4.2 CPU利用率 CPU利用率表示在一段时间内的繁忙程度,用时…...
数字化转型能带来哪些价值?_光点科技
随着科技的迅猛发展,数字化转型已成为企业和组织的一项重要战略。它不仅改变了商业模式和运营方式,还为各行各业带来了诸多新的机遇和价值。在这篇文章中,我们将探讨数字化转型所能带来的价值。 数字化转型能够显著提升效率和生产力。通过引入…...
适用于Android™的Windows子系统Windows Subsystem fo r Android™Win11安装指南
文章目录 一、需求二、Windows Subsystem for Android™Win11简介三、安装教程1.查看BIOS是否开启虚拟化2.安装Hyper-V、虚拟机平台3.启动虚拟机管理程序(可选)4.安装适用于Android™的Windows子系统5.相关设置 一、需求 需要在电脑上进行网课APP(无客户端只有App&…...
hive高频使用的拼接函数及“避坑”
hive高频使用的拼接函数及“避坑” 说到拼接函数应用场景和使用频次还是非常高,比如一个员工在公司充当多个角色,我们在底层存数的时候往往是多行,但是应用的时候我们通常会只需要一行,角色字段进行拼接,这样join其他…...
windows ipv4 多ip地址设置,默认网关跃点和自动跃点是什么意思?(跃点数)
文章目录 Windows中的IPv4多IP地址设置以及默认网关跃点和自动跃点的含义引言IPv4和IPv6:简介多IP地址设置:Windows环境中的实现默认网关跃点:概念和作用自动跃点:何时使用?关于“跃点数”如何确定应该设置多少跃点数&…...
java_免费文本翻译API_小牛翻译
目录 前言 开始集成API 纯文本翻译接口 双语对照翻译接口 指定术语翻译接口 总结 前言 网络上对百度,有道等的文本翻译API集成的文章比较多,所以集成的第一篇选择了小牛翻译的文本翻译API。 小牛翻译文本翻译API,支持388个语种࿰…...
flink消费kafka数据,按照指定时间开始消费
kafka中根据时间戳开始消费数据 import org.apache.flink.api.java.utils.ParameterTool; import org.apache.flink.connector.kafka.source.enumerator.initializer.OffsetsInitializer; import org.apache.flink.kafka.shaded.org.apache.kafka.clients.consumer.OffsetRese…...
【SpringCloud】Feign使用
文章目录 配置maven启动类添加yml 使用添加Feign服务Controller 其他设置超时设置YML开启OpenFeign客户端超时控制(Ribbon Timeout)OpenFeign日志打印功能日志级别YML开启日志 配置 maven <dependencies><!--openfeign--><dependency&g…...
WebApIs 第五天
window对象 BOM(浏览器对象模型)定时器-延时函数JS执行机制location对象navigator对象histroy对象 本地存储 一.BOM(浏览器对象模型) ① BOM是浏览器对象模型 window 对象是一个全局对象,也可以说是JavaScript中的…...
按斤称的C++散知识
一、多线程 std::thread()、join() 的用法:使用std::thread()可以创建一个线程,同时指定线程执行函数以及参数,同时也可使用lamda表达式。 #include <iostream> #include <thread>void threadFunction(int num) {std::cout <…...
C++策略模式
1 简介: 策略模式是一种行为型设计模式,用于在运行时根据不同的情况选择不同的算法或行为。它将算法封装成一个个具体的策略类,并使这些策略类可以相互替换,以达到动态改变对象的行为的目的。 2 实现步骤: 以下是使用…...
如何在网页下载腾讯视频为本地MP4格式
1.打开腾讯视频官网地址 腾讯视频 2.搜索你想要下载的视频 3. 点击分享,选择复制通用代码 <iframe frameborder="0" src="ht...
opencv-yolov8-目标检测
import cv2 from ultralytics import YOLO# 模型加载权重model YOLO(yolov8n.pt)# 视频路径cap cv2.VideoCapture(0)# 对视频中检测到目标画框标出来 while cap.isOpened():# Read a frame from the videosuccess, frame cap.read()if success:# Run YOLOv8 inference on th…...
CRYPTO 密码学-笔记
一、古典密码学 1.替换法:用固定的信息,将原文替换成密文 替换法的加密方式:一种是单表替换,另一种是多表替换 单表替换:原文和密文使用同一张表 abcde---》sfdgh 多表替换:有多涨表,原文和密文…...
基于YOLOv8模型的五类动物目标检测系统(PyTorch+Pyside6+YOLOv8模型)
摘要:基于YOLOv8模型的五类动物目标检测系统可用于日常生活中检测与定位动物目标(狼、鹿、猪、兔和浣熊),利用深度学习算法可实现图片、视频、摄像头等方式的目标检测,另外本系统还支持图片、视频等格式的结果可视化与…...
Java课题笔记~ SpringBoot基础配置
二、基础配置 1. 配置文件格式 问题导入 框架常见的配置文件有哪几种形式? 1.1 修改服务器端口 http://localhost:8080/books/1 >>> http://localhost/books/1 SpringBoot提供了多种属性配置方式 application.properties server.port80 applicati…...
vue实现文件上传,前后端
前端封装el-upload组件,父组件传值dialogVisible(用于显示el-dialog),子组件接收,并且关闭的时候返回一个值(用于隐藏el-dialog),最多上传五个文件,文件格式为.jpg\pdf\png <tem…...
OJ练习第151题——克隆图
克隆图 力扣链接:133. 克隆图 题目描述 给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。 示例 分析 对于一张图而言,它的深拷贝即构建一张与原图结构,值均一样的图,但是…...
技术无罪,人心可畏 —— 写在 315 “GEO 投毒” 话题之后
2026 年央视 315 晚会,将镜头对准了人工智能领域的灰色地带 ——“AI 投毒” 与 “GEO” 一夜之间成为公众热议的话题。记者虚构了一款名为 “Apollo-9” 的智能手环,借助 “GEO 优化系统” 批量生成虚假内容,短短数小时就让多个主流 AI 大模…...
OFA-VE环境部署:Python 3.11+PyTorch+CUDA一站式配置手册
OFA-VE环境部署:Python 3.11PyTorchCUDA一站式配置手册 1. 引言:认识OFA-VE视觉推理系统 OFA-VE是一个基于阿里巴巴达摩院OFA大模型构建的多模态推理平台,专门用于分析图像内容与文本描述之间的逻辑关系。这个系统采用了现代化的赛博朋克视…...
intv_ai_mk11开源模型教程:7B Llama架构对话机器人在GPU云上的安全沙箱实践
intv_ai_mk11开源模型教程:7B Llama架构对话机器人在GPU云上的安全沙箱实践 1. 什么是intv_ai_mk11对话机器人 intv_ai_mk11是一个基于7B参数Llama架构的AI对话助手,专门设计运行在GPU云服务器环境中。这个模型经过优化,能够在保持较高响应…...
从预测到归因:手把手教你用因果森林(grf)做特征重要性分析与亚组发现
从预测到归因:手把手教你用因果森林(grf)做特征重要性分析与亚组发现 在金融风控、个性化营销和医疗疗效评估等领域,我们常常面临一个关键问题:干预措施的效果是否存在显著差异?传统分析方法如A/B测试能告诉…...
音乐自由之路:Unlock-Music技术突破实战指南
音乐自由之路:Unlock-Music技术突破实战指南 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库: 1. https://github.com/unlock-music/unlock-music ;2. https://git.unlock-music.dev/um/web 项目地址: https://gitcod…...
SPIRAN ART SUMMONER图像生成前端展示效果优化技巧
SPIRAN ART SUMMONER图像生成前端展示效果优化技巧 1. 引言 你有没有遇到过这种情况:用SPIRAN ART SUMMONER生成了超棒的图片,但在网站上展示时却加载缓慢,用户还没看到效果就流失了?或者图片显示不完整,影响了整体的…...
Vivado项目文件太多分不清?这份FPGA开发必备的‘文件后缀速查手册’请收好
Vivado项目文件管理终极指南:从后缀识别到高效工作流 当你第一次打开一个成熟的Vivado项目文件夹时,那种面对几十种陌生文件后缀的茫然感,相信每个FPGA开发者都记忆犹新。就像走进了一个满是神秘符号的仓库,每个文件似乎都在向你发…...
Spring Boot 3.0 + Java 17 微服务实战:用Gradle统一管理多模块依赖与版本,告别配置混乱
Spring Boot 3.0 Java 17 微服务实战:用Gradle统一管理多模块依赖与版本 在微服务架构中,依赖管理往往成为开发者的噩梦。想象一下,当你需要在十几个子模块中同步更新Spring Boot版本时,传统的做法是在每个模块的构建文件中逐一修…...
Qt QTabWidget标签页文字方向调校实战:当标签在左侧时,如何让文字乖乖水平显示?
Qt QTabWidget标签页文字方向调校实战:当标签在左侧时,如何让文字乖乖水平显示? 在桌面应用开发中,Qt框架的QTabWidget组件因其灵活性和易用性广受开发者青睐。但当我们尝试将标签页位置调整为左侧时,一个令人头疼的问…...
nlp_structbert_sentence-similarity_chinese-large保姆级教学:模型路径自定义、多模型切换、Web界面汉化配置
nlp_structbert_sentence-similarity_chinese-large保姆级教学:模型路径自定义、多模型切换、Web界面汉化配置 1. 引言:为什么需要这个工具? 你是不是经常遇到这样的情况:需要判断两段中文文字是不是表达同一个意思,…...
