设计模式-行为型模式:观察者模式
目录
1、简介
2、组成部分
3、优缺点
4、使用场景
5、代码实现
1、简介
观察者模式是一种软件设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,当主题对象发生变化时,所有的观察者对象都会得到通知并且自动更新。
2、组成部分
观察者模式中的三个核心角色包括:
- 主题(Subject):被观察的对象,通常会维护一个观察者列表,以便在状态发生变化时通知观察者。
- 观察者(Observer):观察主题对象的状态变化,当主题状态发生变化时,观察者将得到通知并执行相应的操作。
- 具体主题(ConcreteSubject):具体的主题实现类,负责维护一个观察者列表,并实现主题对象状态变化的通知逻辑。
- 具体观察者(ConcreteObserver):具体的观察者实现类,实现观察者接口,并定义观察者接收到通知后的具体操作。
3、优缺点
观察者模式的优点包括:
- 降低对象之间的耦合性:主题对象和观察者对象之间的关系是松散的,它们之间并没有直接依赖关系,使得它们之间的交互变得灵活和可扩展。
- 符合“开闭原则”:当需要增加新的观察者对象时,不需要修改主题对象的代码,只需要增加一个新的具体观察者即可。
- 支持广播通信:主题对象可以同时通知多个观察者对象,使得多个观察者对象可以同时对主题对象的状态变化进行响应。
观察者模式的缺点包括:
- 观察者数量过多会导致性能问题:如果观察者数量过多,每次状态变化都需要通知所有的观察者对象,会导致性能问题。
- 观察者与主题的依赖关系可能会导致循环引用:观察者对象和主题对象之间是相互依赖的,如果设计不当可能会导致循环引用问题。
- 可能会出现状态不一致问题:如果观察者对象在收到通知后执行的操作与主题对象的状态更新操作不同步,可能会导致观察者对象的状态与主题对象的状态不一致。
- 观察者对象接收到的通知是有序的:通知的顺序可能会影响观察者对象的执行结果,如果观察者对象之间有相互依赖关系,可能会影响整个系统的正确性。
- 观察者模式可能会导致性能问题题:如果主题对象在通知观察者对象时,需要执行较为复杂的操作,可能会影响整个系统的性能。
总体来说,观察者模式是一种很有用的设计模式,它可以实现对象之间的松耦合,提高代码的可维护性和可扩展性。但是在使用时需要注意上述缺点,并结合具体的业务场景进行选择。
4、使用场景
观察者模式的使用场景包括:
- 一个对象的状态变化会影响其他对象:当一个对象的状态发生变化时,其他多个对象需要做出相应的响应,此时可以使用观察者模式。
- 对象的状态更新频繁且多个对象需要及时更新:如果一个对象的状态更新非常频繁,多个对象需要及时更新状态,那么使用观察者模式可以提高程序的效率。
- 对象需要在不同的情况下通知不同的观察者对象:当对象需要在不同的情况下通知不同的观察者对象时,可以使用观察者模式。这种情况下,每个观察者对象只需要关注它所感兴趣的通知即可。
- 想要实现事件监听器:当需要在程序中实现事件监听器时,可以使用观察者模式。例如,在Java中,可以使用Swing框架中的观察者模式来实现图形界面组件的事件监听器。
- MVC模式中的视图与模型:在MVC(Model-View-Controller)模式中,视图层需要对模型层进行监听,当模型层发生变化时,视图层需要及时更新自己的显示。此时可以使用观察者模式,将视图层作为观察者对象,将模型层作为主题对象。
总之,当需要在多个对象之间实现松耦合的消息传递时,可以考虑使用观察者模式。观察者模式适用于需要动态更新的场景,可以帮助我们将代码设计得更加灵活和可扩展。
5、代码实现
下面是一个使用Java实现观察者模式的示例,并对代码进行详细说明:
1、首先定义主题接口Subject和观察者接口Observer:
public interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}
public interface Observer {void update(float temperature, float humidity, float pressure);
}
2、定义具体的主题类WeatherData,实现Subject接口:
import java.util.ArrayList;public class WeatherData implements Subject {private ArrayList<Observer> observers;private float temperature;private float humidity;private float pressure;public WeatherData() {observers = new ArrayList<>();}public void registerObserver(Observer observer) {observers.add(observer);}public void removeObserver(Observer observer) {int index = observers.indexOf(observer);if (index >= 0) {observers.remove(index);}}public void notifyObservers() {for (Observer observer : observers) {observer.update(temperature, humidity, pressure);}}public void measurementsChanged() {notifyObservers();}public void setMeasurements(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;measurementsChanged();}
}
3、定义具体的观察者类CurrentConditionsDisplay,实现Observer接口:
public class CurrentConditionsDisplay implements Observer {private float temperature;private float humidity;private float pressure;private Subject weatherData;public CurrentConditionsDisplay(Subject weatherData) {this.weatherData = weatherData;weatherData.registerObserver(this);}public void update(float temperature, float humidity, float pressure) {this.temperature = temperature;this.humidity = humidity;this.pressure = pressure;display();}public void display() {System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");}
}
4、编写测试代码:
public class WeatherStation {public static void main(String[] args) {WeatherData weatherData = new WeatherData();CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);weatherData.setMeasurements(80, 65, 30.4f);weatherData.setMeasurements(82, 70, 29.2f);weatherData.setMeasurements(78, 90, 29.2f);}
}
运行以上代码,输出结果如下:
Current conditions: 80.0F degrees and 65.0% humidity
Current conditions: 82.0F degrees and 70.0% humidity
Current conditions: 78.0F degrees and 90.0% humidity
以上代码演示了观察者模式的基本实现,具体说明如下:
- WeatherData类是主题类,它维护了一个观察者列表,实现了Subject接口中的三个方法:registerObserver、removeObserver和notifyObservers,用来注册观察者、移除观察者和通知观察者。WeatherData类还定义了一个measurementsChanged方法,用来在气象数据发生变化时通知观察者。
- CurrentConditionsDisplay类是观察者类,它实现了Observer接口中的update方法,用来更新观测值,并调用display方法展示当前观测值。CurrentConditionsDisplay类还在构造方法中注册到主题类中,以便接收气象数据的变化通知。
- WeatherStation类是测试类,创建了WeatherData和CurrentConditionsDisplay对象,并通过调用setMeasurements方法模拟气象数据的变化,然后观察当前观测值是否会被更新和显示出来。
观察者模式的实现可以让主题类和观察者类分离,使它们之间的依赖性降到最低,提高了代码的灵活性和可扩展性。当主题对象发生变化时,所有注册的观察者对象都会收到通知,可以进行相应的处理,实现了松耦合。
需要注意的是,观察者模式也存在一些缺点。当观察者对象较多时,主题对象的通知会导致较大的开销;观察者对象需要实现update方法,这可能会导致代码的复杂性增加。因此,在使用观察者模式时需要根据具体情况进行权衡和选择。
相关文章:
设计模式-行为型模式:观察者模式
目录 1、简介 2、组成部分 3、优缺点 4、使用场景 5、代码实现 1、简介 观察者模式是一种软件设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,当主题对象发生变化时,所有的观察者对象都会得到…...

Springboot 为了偷懒,我封装了一个自适配的数据单位转换工具类
前言 平时做一些统计数据,经常从数据库或者是从接口获取出来的数据,单位是跟业务需求不一致的。 比如, 我们拿出来的 分, 实际上要是元 又比如,我们拿到的数据需要 乘以100 返回给前端做 百分比展示 又比如ÿ…...

正则表达式
当我们需要对字符串进行判断的时候,使用正则表达式能大大提高编程效率。比如,当我们需要找出所有“像邮箱”的字符串(包含"" "." ".com",且顺序一致),我们需要一个某种模式的…...

java进阶Map 集合
通过之前的学习我们知道Map是一个双列集合,就是以键值对的形式进行数据存储 java进阶—集合 Map 下面有 三个子接口,HashMap , HashTable 以及 TreeMap 提醒一点:Map不是Collection下的集合,Collection是单列集合&am…...

Java 方法超详细整理,适合新手入门
目录 一、什么是方法呢? 二、方法的优点 三、带返回值方法定义 语法: 示例: 四、带返回值方法调用 语法: 示例: 五、结果示例 一、什么是方法呢? Java方法是语句的集合,它们在一起执行…...

软考学习笔记(题目知识记录)
答案为 概要设计阶段 本题涉及软件工程的概念 软件工程的任务是基于需求分析的结果建立各种设计模型,给出问题的解决方案 软件设计可以分为两个阶段: 概要设计阶段和详细设计阶段 结构化设计方法中,概要设计阶段进行软件体系结构的设计&…...

2021.3.3idea创建Maven项目
首先new - project - 找到Maven 然后按下图操作:先勾选使用骨架,再找到Maven-archetype-webapp,选中,然后next填写自己想要创建的项目名,然后选择自己的工作空间①、选择自己下载的Maven插件②、选择选择Maven里的sett…...

ASP.NET MVC | 创建应用程序
目录 首先 NO.1 No.2 App_Data 文件夹 Content 文件夹 Controllers 文件夹 Models 文件夹 Views 文件夹 Scripts 文件夹 最后 首先 一步一步的来,电脑上需要安装vs2019软件,版本高低无所谓,就是功能多少而已。 长这样的࿰…...
思科设备命令讲解(超基础)
♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️夕阳下,是最美的绽放࿰…...

Qt-FFmpeg开发-保存视频流裸流(11)
Qt-FFmpeg开发-保存视频流裸流📀 文章目录Qt-FFmpeg开发-保存视频流裸流📀1、概述📸2、实现效果💽3、FFmpeg保存裸流代码流程💡4、主要代码🔍5、完整源代码📑更多精彩内容👉个人内容…...

Zebec官方辟谣“我们与Protradex没有任何关系”
近日,流支付协议Zebec Protocol在其官方推特上,发表了一个辟谣澄清声明。该条推特推文表示,“Zebec 与 Protradex 没有任何关系或产生关联。他们( Protradex )声称Zebec 生态正在支持他们,但这是错误的。随…...
BMS电池管理系统中的各种算法介绍
BMS电池管理系统 是一种用于电池组中的单个电池管理的系统,以确保其安全性、寿命和性能。BMS系统通过采集电池信息并对其进行分析,以确保电池组的正常运行。在BMS电池管理系统中,涉及到了许多算法,包括最大功率点追踪算法、SOC计算…...
stack Overflow 的使用
文章目录优雅的搜索1.1要在特定标签内搜索1.2搜索特定的短语1.3 限定检索位置1.4选择性屏蔽优雅的筛选搜索结果1. 返回的搜索筛选2. 特定时间段的帖子3. 精准的BOOL判断4. 其他的例子优雅的搜索 其实,在Stack OverFlow上的搜索方式,与国内的百度没什么大…...

Vue 在for循环中动态添加类名及style样式集合
介绍 在vue的 for 循环中,经常会使用到动态添加类名或者样式的情况,实现给当前的选中的 div 添加不同的样式。 动态添加类名 提示: 所有动态添加的类名,放在表达式里都需要添加引号,进行包裹。 通过 对象 的形式&a…...
Maven的优势
作用一:个人理解maven主要是用来解决导入java类依赖的jar,编译java项目主要问题。(最早手动导入jar,使用Ant之类的编译java项目)以pom.xml文件中dependency属性管理依赖的jar包,而jar包包含class文件和一些必要的资源文件。当然它可以构建项目…...
uboot,内核,根文件系统的作用
复习了下uboot,内核,根文件系统,简单概括下三者的主要内容。 1 uboot uboot的目的:启动内核。 uboot的功能可以分为两个阶段任务。 1.2.1 uboot第一阶段 uboot第一阶段主要负责硬件相关的初始化,主要在cpu/arm920…...

Vue3通透教程【四】Vue3组合API初体验
文章目录🌟 写在前面🌟 组合式 API 是什么?🌟 直观组合式API🌟 写在最后🌟 写在前面 专栏介绍: 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章,应粉丝要求开始更新 Vue3 的相关技…...

coco数据集训练nanodet详细流程
github地址 首先要配置环境 conda create -n nanodet python3.8 -y conda activate nanodet确认一下cuda版本 nvcc -V确认是11.3之后,要安装11.3对应的pytorch版本。 本机装pytorch1.12.1后面运行的时候会报错(torch没有经过cuda编译)&…...

关于Kubernetes不兼容Docker
本博客地址:https://security.blog.csdn.net/article/details/129153459 参考文献:https://www.cnblogs.com/1234roro/p/16892031.html 一、总结 总结起来就是一句话: k8s只是弃用了dockershim,并不是弃用了整个Docker…...

MySql_基础篇_从下载mysq到数据库操作
本笔记基于b站up主黑马程序员的视频整理 用于记录与回顾 数据库相关概念 数据库 DS 存储数据的仓库 数据库管理系统 DSMS 操纵和管理数据库的大型软件 sql 操作关系型数据库的编程语言是一套标准 mysql 默认端口号是3306 下载数据库 社区版下载 https://dev.mysql.com/…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...

PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...