当前位置: 首页 > news >正文

设计模式-行为型模式:观察者模式

目录

1、简介

2、组成部分

3、优缺点

4、使用场景

5、代码实现


1、简介

观察者模式是一种软件设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,当主题对象发生变化时,所有的观察者对象都会得到通知并且自动更新。

2、组成部分

观察者模式中的三个核心角色包括:

  1. 主题(Subject):被观察的对象,通常会维护一个观察者列表,以便在状态发生变化时通知观察者。
  2. 观察者(Observer):观察主题对象的状态变化,当主题状态发生变化时,观察者将得到通知并执行相应的操作。
  3. 具体主题(ConcreteSubject):具体的主题实现类,负责维护一个观察者列表,并实现主题对象状态变化的通知逻辑。
  4. 具体观察者(ConcreteObserver):具体的观察者实现类,实现观察者接口,并定义观察者接收到通知后的具体操作。

3、优缺点

观察者模式的优点包括:

  1. 降低对象之间的耦合性:主题对象和观察者对象之间的关系是松散的,它们之间并没有直接依赖关系,使得它们之间的交互变得灵活和可扩展。
  2. 符合“开闭原则”:当需要增加新的观察者对象时,不需要修改主题对象的代码,只需要增加一个新的具体观察者即可。
  3. 支持广播通信:主题对象可以同时通知多个观察者对象,使得多个观察者对象可以同时对主题对象的状态变化进行响应。

观察者模式的缺点包括:

  1. 观察者数量过多会导致性能问题:如果观察者数量过多,每次状态变化都需要通知所有的观察者对象,会导致性能问题。
  2. 观察者与主题的依赖关系可能会导致循环引用:观察者对象和主题对象之间是相互依赖的,如果设计不当可能会导致循环引用问题。
  3. 可能会出现状态不一致问题:如果观察者对象在收到通知后执行的操作与主题对象的状态更新操作不同步,可能会导致观察者对象的状态与主题对象的状态不一致。
  4. 观察者对象接收到的通知是有序的:通知的顺序可能会影响观察者对象的执行结果,如果观察者对象之间有相互依赖关系,可能会影响整个系统的正确性。
  5. 观察者模式可能会导致性能问题题:如果主题对象在通知观察者对象时,需要执行较为复杂的操作,可能会影响整个系统的性能。

总体来说,观察者模式是一种很有用的设计模式,它可以实现对象之间的松耦合,提高代码的可维护性和可扩展性。但是在使用时需要注意上述缺点,并结合具体的业务场景进行选择。

4、使用场景

观察者模式的使用场景包括:

  1. 一个对象的状态变化会影响其他对象:当一个对象的状态发生变化时,其他多个对象需要做出相应的响应,此时可以使用观察者模式。
  2. 对象的状态更新频繁且多个对象需要及时更新:如果一个对象的状态更新非常频繁,多个对象需要及时更新状态,那么使用观察者模式可以提高程序的效率。
  3. 对象需要在不同的情况下通知不同的观察者对象:当对象需要在不同的情况下通知不同的观察者对象时,可以使用观察者模式。这种情况下,每个观察者对象只需要关注它所感兴趣的通知即可。
  4. 想要实现事件监听器:当需要在程序中实现事件监听器时,可以使用观察者模式。例如,在Java中,可以使用Swing框架中的观察者模式来实现图形界面组件的事件监听器。
  5. 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、简介 观察者模式是一种软件设计模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听一个主题对象&#xff0c;当主题对象发生变化时&#xff0c;所有的观察者对象都会得到…...

Springboot 为了偷懒,我封装了一个自适配的数据单位转换工具类

前言 平时做一些统计数据&#xff0c;经常从数据库或者是从接口获取出来的数据&#xff0c;单位是跟业务需求不一致的。 比如&#xff0c; 我们拿出来的 分&#xff0c; 实际上要是元 又比如&#xff0c;我们拿到的数据需要 乘以100 返回给前端做 百分比展示 又比如&#xff…...

正则表达式

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

java进阶Map 集合

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

Java 方法超详细整理,适合新手入门

目录 一、什么是方法呢&#xff1f; 二、方法的优点 三、带返回值方法定义 语法&#xff1a; 示例&#xff1a; 四、带返回值方法调用 语法&#xff1a; 示例&#xff1a; 五、结果示例 一、什么是方法呢&#xff1f; Java方法是语句的集合&#xff0c;它们在一起执行…...

软考学习笔记(题目知识记录)

答案为 概要设计阶段 本题涉及软件工程的概念 软件工程的任务是基于需求分析的结果建立各种设计模型&#xff0c;给出问题的解决方案 软件设计可以分为两个阶段&#xff1a; 概要设计阶段和详细设计阶段 结构化设计方法中&#xff0c;概要设计阶段进行软件体系结构的设计&…...

2021.3.3idea创建Maven项目

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

ASP.NET MVC | 创建应用程序

目录 首先 NO.1 No.2 App_Data 文件夹 Content 文件夹 Controllers 文件夹 Models 文件夹 Views 文件夹 Scripts 文件夹 最后 首先 一步一步的来&#xff0c;电脑上需要安装vs2019软件&#xff0c;版本高低无所谓&#xff0c;就是功能多少而已。 长这样的&#xff0…...

思科设备命令讲解(超基础)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的绽放&#xff0…...

Qt-FFmpeg开发-保存视频流裸流(11)

Qt-FFmpeg开发-保存视频流裸流&#x1f4c0; 文章目录Qt-FFmpeg开发-保存视频流裸流&#x1f4c0;1、概述&#x1f4f8;2、实现效果&#x1f4bd;3、FFmpeg保存裸流代码流程&#x1f4a1;4、主要代码&#x1f50d;5、完整源代码&#x1f4d1;更多精彩内容&#x1f449;个人内容…...

Zebec官方辟谣“我们与Protradex没有任何关系”

近日&#xff0c;流支付协议Zebec Protocol在其官方推特上&#xff0c;发表了一个辟谣澄清声明。该条推特推文表示&#xff0c;“Zebec 与 Protradex 没有任何关系或产生关联。他们&#xff08; Protradex &#xff09;声称Zebec 生态正在支持他们&#xff0c;但这是错误的。随…...

BMS电池管理系统中的各种算法介绍

BMS电池管理系统 是一种用于电池组中的单个电池管理的系统&#xff0c;以确保其安全性、寿命和性能。BMS系统通过采集电池信息并对其进行分析&#xff0c;以确保电池组的正常运行。在BMS电池管理系统中&#xff0c;涉及到了许多算法&#xff0c;包括最大功率点追踪算法、SOC计算…...

stack Overflow 的使用

文章目录优雅的搜索1.1要在特定标签内搜索1.2搜索特定的短语1.3 限定检索位置1.4选择性屏蔽优雅的筛选搜索结果1. 返回的搜索筛选2. 特定时间段的帖子3. 精准的BOOL判断4. 其他的例子优雅的搜索 其实&#xff0c;在Stack OverFlow上的搜索方式&#xff0c;与国内的百度没什么大…...

Vue 在for循环中动态添加类名及style样式集合

介绍 在vue的 for 循环中&#xff0c;经常会使用到动态添加类名或者样式的情况&#xff0c;实现给当前的选中的 div 添加不同的样式。 动态添加类名 提示&#xff1a; 所有动态添加的类名&#xff0c;放在表达式里都需要添加引号&#xff0c;进行包裹。 通过 对象 的形式&a…...

Maven的优势

作用一&#xff1a;个人理解maven主要是用来解决导入java类依赖的jar,编译java项目主要问题。(最早手动导入jar&#xff0c;使用Ant之类的编译java项目)以pom.xml文件中dependency属性管理依赖的jar包&#xff0c;而jar包包含class文件和一些必要的资源文件。当然它可以构建项目…...

uboot,内核,根文件系统的作用

复习了下uboot&#xff0c;内核&#xff0c;根文件系统&#xff0c;简单概括下三者的主要内容。 1 uboot uboot的目的&#xff1a;启动内核。 uboot的功能可以分为两个阶段任务。 1.2.1 uboot第一阶段 uboot第一阶段主要负责硬件相关的初始化&#xff0c;主要在cpu/arm920…...

Vue3通透教程【四】Vue3组合API初体验

文章目录&#x1f31f; 写在前面&#x1f31f; 组合式 API 是什么&#xff1f;&#x1f31f; 直观组合式API&#x1f31f; 写在最后&#x1f31f; 写在前面 专栏介绍&#xff1a; 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章&#xff0c;应粉丝要求开始更新 Vue3 的相关技…...

coco数据集训练nanodet详细流程

github地址 首先要配置环境 conda create -n nanodet python3.8 -y conda activate nanodet确认一下cuda版本 nvcc -V确认是11.3之后&#xff0c;要安装11.3对应的pytorch版本。 本机装pytorch1.12.1后面运行的时候会报错&#xff08;torch没有经过cuda编译&#xff09;&…...

关于Kubernetes不兼容Docker

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

MySql_基础篇_从下载mysq到数据库操作

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

Stitches API完全指南:从基础配置到自定义扩展

Stitches API完全指南&#xff1a;从基础配置到自定义扩展 【免费下载链接】stitches HTML5 Sprite Sheet Generator 项目地址: https://gitcode.com/gh_mirrors/sti/stitches Stitches是一款强大的HTML5 Sprite Sheet Generator&#xff0c;它提供了直观的API接口&…...

为什么92%的DeepSeek二次开发团队在6个月内遭遇交付延迟?——基于17个真实项目的技术债务归因分析

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;为什么92%的DeepSeek二次开发团队在6个月内遭遇交付延迟&#xff1f;——基于17个真实项目的技术债务归因分析 在对17个采用DeepSeek-R1/VL模型开展定制化开发的工业级项目进行回溯审计后&#xff0c;我…...

我靠这个测试设计方法,把漏测率降低了80%

当“直觉测试”撞上南墙很长一段时间里&#xff0c;我和许多测试同行一样&#xff0c;测试用例的设计主要依靠两样东西&#xff1a;需求文档和“测试直觉”。这种模式在业务逻辑相对简单、迭代速度平缓时还能勉强应付。一旦面对复杂的企业级应用、高频的敏捷迭代&#xff0c;或…...

AI IDE 革命:程序员正在被重新定义

很多开发者第一次使用 Cursor 的 CtrlK 或 Composer&#xff08;高级多文件编辑模式&#xff09;时&#xff0c;都会有一种强烈的、甚至让人有些脊背发凉的冲击感。 因为&#xff1a; 它已经不再是那个我们熟悉的、只能在原地等待光标落下的&#xff1a; “代码自动补全插件&am…...

在Hermes Agent项目中接入Taotoken作为自定义模型供应商

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 在Hermes Agent项目中接入Taotoken作为自定义模型供应商 基础教程类&#xff0c;针对使用Hermes Agent框架的开发者&#xff0c;详…...

Performance-Fish:让你的《环世界》后期游戏帧率提升400%的终极优化方案

Performance-Fish&#xff1a;让你的《环世界》后期游戏帧率提升400%的终极优化方案 【免费下载链接】Performance-Fish Performance Mod for RimWorld 项目地址: https://gitcode.com/gh_mirrors/pe/Performance-Fish 你是否曾在《环世界》游戏后期&#xff0c;面对庞大…...

对比自行维护多个 API 源,使用 Taotoken 聚合服务在运维复杂度上的降低

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 对比自行维护多个 API 源&#xff0c;使用 Taotoken 聚合服务在运维复杂度上的降低 在构建依赖多个大语言模型的应用时&#xff0c…...

从模糊到电影级景深:Midjourney + Topaz Gigapixel联调方案(含LUT预设包+PSD分层模板)

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;从模糊到电影级景深&#xff1a;Midjourney Topaz Gigapixel联调方案&#xff08;含LUT预设包PSD分层模板&#xff09; 当Midjourney生成的图像存在主体边缘柔化、背景层次缺失或分辨率不足等问题时&#xf…...

招行+工行:ReAct(Reasoning + Acting) 讲清楚,并结合 金融场景(含自进化智能体) 给出可直接用的案例

下面我把 ReAct&#xff08;Reasoning Acting&#xff09; 讲清楚&#xff0c;并结合 ** 金融场景&#xff08;含自进化智能体&#xff09;** 给出可直接用的案例与话术&#xff0c;适合分享 / 汇报。一、ReAct 是什么&#xff08;一句话&#xff09;ReAct 推理&#xff08;T…...

基于Arduino与蓝牙模块的六路无线开关控制系统设计与实现

1. 项目概述&#xff1a;用手机蓝牙控制六路LED想不想把手机变成一个无线遥控器&#xff0c;随手一点就能开关家里的灯带、氛围灯&#xff0c;甚至是其他电器&#xff1f;这个项目就是为你准备的。它基于一块功能增强的Arduino兼容板——GlowDuino Uno&#xff0c;配合一个极其…...