Spring框架之观察者模式 (Observer Pattern)

观察者模式(Observer Pattern)详解

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象间的一种 一对多 的依赖关系,使得当一个对象的状态发生改变时,其相关依赖对象能够自动接收到通知并进行相应的更新。观察者模式广泛应用于事件驱动的系统中,是 GUI 应用程序、事件系统、消息推送等场景中的核心设计模式。

1. 观察者模式的定义

1.1 什么是观察者模式?

观察者模式,也称为 发布-订阅模式(Publish-Subscribe Pattern),其核心思想是 “观察者订阅被观察者”。当被观察者(也称为 主题(Subject))的状态发生变化时,所有已订阅的观察者(Observer)都会收到通知,并根据通知做出相应的反应。

1.2 观察者模式的结构

观察者模式通常包含以下几个角色:

  1. Subject(被观察者/主题)
    • 维护一个观察者列表。
    • 提供注册、注销观察者的方法。
    • 当状态改变时,通知所有观察者。
  2. Observer(观察者)
    • 定义一个更新接口,用于接收通知。
  3. ConcreteSubject(具体被观察者)
    • 继承 Subject,实现具体的通知逻辑。
  4. ConcreteObserver(具体观察者)
    • 继承 Observer,实现具体的响应逻辑。

2. 观察者模式的类图

+-----------------+        +----------------+
|   Subject       |<>----->|   Observer     |
+-----------------+        +----------------+
| + attach()      |        | + update()     |
| + detach()      |        +----------------+
| + notify()      |              ^
+-----------------+              |^                         ||                         |
+-----------------+        +--------------------+
| ConcreteSubject |        | ConcreteObserver   |
+-----------------+        +--------------------+
| - state         |        | - observerState    |
| + getState()    |        | + update()         |
| + setState()    |        +--------------------+
+-----------------+

3. 观察者模式的实现

以下是一个简单的观察者模式示例。在该示例中,假设有一个天气站(WeatherStation)作为被观察者,多个显示设备(DisplayDevice)作为观察者,天气站会将温度变化通知给所有已注册的显示设备。

3.1 Java 示例代码
import java.util.ArrayList;
import java.util.List;// 观察者接口
interface Observer {void update(float temperature);
}// 被观察者接口
interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers();
}// 具体的被观察者:天气站
class WeatherStation implements Subject {private List<Observer> observers;private float temperature;public WeatherStation() {this.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(temperature);}}// 设置新的温度并通知观察者public void setTemperature(float temperature) {this.temperature = temperature;notifyObservers();}
}// 具体的观察者:手机显示设备
class PhoneDisplay implements Observer {private String name;public PhoneDisplay(String name) {this.name = name;}@Overridepublic void update(float temperature) {System.out.println(name + " 显示温度更新为: " + temperature + "°C");}
}// 具体的观察者:平板显示设备
class TabletDisplay implements Observer {@Overridepublic void update(float temperature) {System.out.println("平板设备显示温度更新为: " + temperature + "°C");}
}// 测试客户端
public class ObserverPatternDemo {public static void main(String[] args) {// 创建被观察者(天气站)WeatherStation weatherStation = new WeatherStation();// 创建观察者PhoneDisplay phoneDisplay = new PhoneDisplay("手机设备1");TabletDisplay tabletDisplay = new TabletDisplay();// 注册观察者weatherStation.registerObserver(phoneDisplay);weatherStation.registerObserver(tabletDisplay);// 更新天气并通知观察者weatherStation.setTemperature(25.5f);weatherStation.setTemperature(30.0f);// 移除一个观察者weatherStation.removeObserver(phoneDisplay);weatherStation.setTemperature(28.5f);}
}

输出结果

手机设备1 显示温度更新为: 25.5°C
平板设备显示温度更新为: 25.5°C
手机设备1 显示温度更新为: 30.0°C
平板设备显示温度更新为: 30.0°C
平板设备显示温度更新为: 28.5°C

4. 观察者模式的应用场景

观察者模式广泛应用于各种需要事件通知的场景中:

  1. GUI 事件监听
    • 在图形用户界面中,如按钮点击、文本框输入变化等事件处理机制。
  2. MVC 架构
    • 在 MVC 设计模式中,视图(View)会观察模型(Model)的变化,当模型的数据发生变化时,视图会自动更新。
  3. 推送通知系统
    • 应用程序中的消息推送服务、实时更新、订阅发布系统(如 RSS、社交媒体通知)。
  4. 缓存刷新机制
    • 当缓存数据源发生变化时,通知所有相关缓存进行刷新。
  5. 数据库触发器
    • 在数据库中,当某个表的数据发生变化时,可以触发通知其他表或系统。

5. 观察者模式的优缺点

5.1 优点
  • 降低耦合度:被观察者和观察者之间是松耦合关系。被观察者无需知道观察者的具体实现,符合“依赖倒置原则”。
  • 支持广播通信:一个被观察者可以同时通知多个观察者,扩展性强。
  • 符合开闭原则:可以在不修改被观察者的情况下添加新的观察者,实现系统的灵活扩展。
5.2 缺点
  • 潜在的性能问题:如果有大量的观察者,通知所有观察者可能会带来一定的性能开销。
  • 通知顺序不确定:观察者的通知顺序是不确定的,可能会导致数据不一致的情况。
  • 内存泄漏:如果观察者没有正确注销,可能会导致内存泄漏,尤其是在 Java 等需要手动管理观察者注册和注销的语言中。

6. 观察者模式的扩展

6.1 推模型 vs 拉模型
  • 推模型(Push Model)
    • 被观察者主动将变更数据推送给观察者。适用于数据量小、变化频繁的场景。
  • 拉模型(Pull Model)
    • 被观察者仅通知观察者状态已发生变化,观察者自行拉取所需的数据。适用于数据量大、变化不频繁的场景。
6.2 Java 内置的观察者模式

Java 标准库提供了 java.util.Observable 类和 java.util.Observer 接口来实现观察者模式。

示例

import java.util.Observable;
import java.util.Observer;class NewsAgency extends Observable {private String news;public void setNews(String news) {this.news = news;setChanged(); // 标记状态已改变notifyObservers(news);}
}class NewsChannel implements Observer {@Overridepublic void update(Observable o, Object arg) {System.out.println("新闻频道收到新闻更新: " + arg);}
}public class JavaObserverExample {public static void main(String[] args) {NewsAgency newsAgency = new NewsAgency();NewsChannel newsChannel = new NewsChannel();newsAgency.addObserver(newsChannel);newsAgency.setNews("新冠疫情最新动态!");}
}

输出

新闻频道收到新闻更新: 新冠疫情最新动态!
6.3 RxJava 的响应式编程
  • 在响应式编程中,观察者模式的思想被广泛应用。RxJava 通过 ObservableObserver 提供了更加灵活和功能丰富的 API 来处理异步数据流。

7. 总结

观察者模式是一种非常常用的设计模式,在许多场景下都能提升系统的扩展性和灵活性。它不仅降低了对象之间的耦合度,还能实现事件驱动的机制,使得系统能够动态响应外部的变化。

  • 优点:松耦合、易于扩展、支持广播通信。
  • 缺点:可能导致性能开销、内存泄漏风险。
  • 适用场景:事件监听、推送通知、MVC 设计模式、数据缓存机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/470679.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

读数据质量管理:数据可靠性与数据质量问题解决之道03数据目录

1. 同步数据 1.1. 不同的数据仓库和数据湖通过数据集成层来进行桥接 1.2. AWS Glue、Fivetran和Matillion等数据集成工具从不同来源收集数据&#xff0c;统一这些数据&#xff0c;并将其转换为上游来源 1.3. 数据集成的一个典型用例是收集数据湖的数据并以结构化格式将其加载…

openSUSE 环境下通过 zypper 安装软件

操作场景 为了提升您在云服务器上的软件安装效率&#xff0c;减少下载和安装软件的成本&#xff0c;腾讯云提供了 zypper 下载源。openSUSE 操作系统和部分 SLES 的云服务器用户可通过 zypper 快速安装软件。本文档以 openSUSE 操作系统为例&#xff0c;指导您通过 zypper 快速…

ima.copilot-腾讯智能工作台

一、产品描述 ima.copilot是腾讯推出的基于腾讯混元大模型技术的智能工作台&#xff0c;通过先进的人工智能技术&#xff0c;为用户提供了一个全新的搜读写体验&#xff0c;让知识管理变得更加智能和高效。它不仅是一个工具&#xff0c;更是一个智能的伙伴&#xff0c;能够帮助…

NVIDIA Isaac Sim 仿真平台体验测评

目录 一、引言二、GPU加速相关体验2.1 Isaac Sim GPU 加速体验2.2 GPU加速体验分析 三、AI框架集成相关体验四、学术研究价值五、开发生态六、综合分析6.1 主要优势6.1.1 仿真效率6.1.2 开发便利性6.1.3 与 AI 框架的协同性 6.2 潜在应用场景 七、运行体验与建议7.1 GPU加速与P…

WebRTC API分析

主题 本文详细描述常用的webrtc api 媒体协商类 myPeerConnection.createOffer([options]); var options { offerToReceiveAudio: true, // 告诉另一端&#xff0c;你是否想接收音频&#xff0c;默认true offerToReceiveVideo: true, // 告诉另一端&a…

11张思维导图带你快速学习java

博主主页:【南鸢1.0】 本文专栏&#xff1a;JAVA 本文目录 简介 1.Java SE​编辑 2.Java Web 3.MySQL​编辑 4.前端技术 5.Linux 6.Spring SpringMvc mybatis 7.JVM 8.Springboot 9.Vue 10.SpringCloud 11.常用中间件 总结 简介 Java是一种跨平台的编程语言&am…

Jmeter基础篇(22)服务器性能监测工具Nmon的使用

一、前言 我们在日常做压测的过程中&#xff0c;不仅仅需要监控TPS&#xff0c;响应时间&#xff0c;报错率等这些系统基础性能数据&#xff0c;还需要对服务器的性能&#xff08;如CPU、磁盘、内存、网络IO等&#xff09;做监控&#xff0c;以求对系统运行过程中的硬件性能有…

Unity3D学习FPS游戏(12)敌人检测和攻击玩家

前言&#xff1a;上一篇实现了敌人能动&#xff0c;有了点乐趣&#xff0c;但是敌人和玩家没什么对抗性。本篇将实现敌人追击玩家&#xff0c;并攻击玩家。 敌人攻击玩家 敌人检测玩家目标思路-碰撞检测的Trigger触发实现 敌人攻击目标思路-模仿玩家发射子弹的思路实现 效果 敌…

利用滑动窗口解题

目录 前言&#xff1a; 第一题&#xff1a;209. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; 第二题&#xff1a;1004. 最大连续1的个数 III - 力扣&#xff08;LeetCode&#xff09; 第三题&#xff1a;3. 无重复字符的最长子串 - 力扣&#xff08;LeetCode&…

车载空气净化器语音芯片方案

开发背景&#xff1a; 随着人们生活质量的不断提升和环保意识的日益增强&#xff0c;车内空气质量成为了广大车主关注的焦点。长时间封闭的车厢环境&#xff0c;加之城市空气污染、新车内饰材料释放的有害气体等因素&#xff0c;使得车内空气质量往往不尽如人意&#xff0c;严重…

《MYSQL45讲》误删数据怎么办

对误删数据分类的话&#xff0c;有 1.delete 误删行 2.drop table 或者truncate table 语句误删表 3.使用drop database 误删数据库 4.使用rm命令误删整个MYSQL实例 一&#xff0c;误删行 一下操作前置条件是&#xff1a;binlog的格式是row&#xff0c;并且binglog_row_im…

不对称信息

你买了一辆二手车&#xff0c;你并不知道它出过几次事故&#xff0c;但它之前的车主却对此了如指掌。来买保险的公司都是那些出险概率很大的&#xff08;比如矿工、化工厂&#xff09;&#xff0c;但那些安全的公司很少去买保险&#xff0c;这两种问题都属于信息不对称问题。 …

94个属于一区且接受医工交叉领域投稿的期刊汇总|个人观点·24-11-13

小罗碎碎念 继汇总病理AI的基础模型、病理组学&影像组学的公开数据集以后&#xff0c;我们再来盘一盘医工交叉领域有哪些热门期刊可以投稿。我会分区进行介绍&#xff0c;每个区则会进一步划分学科种类&#xff0c;方便大家选择适合自己的投稿期刊。 这期推文先分享大类属…

网站小程序app怎么查有没有备案?

网站小程序app怎么查有没有备案&#xff1f;只需要官方一个网址就可以&#xff0c;工信部备案查询官网地址有且只有一个&#xff0c;百度搜索 "ICP备案查询" 找到官方gov.cn网站即可查询&#xff01; 注&#xff1a;网站小程序app备案查询&#xff0c;可通过输入单位…

MySQL45讲 第二十讲 幻读是什么,幻读有什么问题?

文章目录 MySQL45讲 第二十讲 幻读是什么&#xff0c;幻读有什么问题&#xff1f;一、幻读的定义二、幻读带来的问题&#xff08;一&#xff09;语义问题&#xff08;二&#xff09;数据一致性问题 三、InnoDB 解决幻读的方法四、总结 MySQL45讲 第二十讲 幻读是什么&#xff0…

FatLab:我的编程课程系列

FatLab 是一款教程类软件。 大概是因为我的编程生涯始于自学&#xff0c;FatLab便也保持了这种气息&#xff1a;从一个“自然生长”的角度提供了一套C语言教程。 教程方面&#xff0c;目前仅完成了《C语言基础要素》系列。正如其名&#xff0c;这个系列仅探讨了语言中非常基础…

冗余连接2 hard题 代随C#写法

此题在卡码网109与力扣685题亦有记载 有一说一C#写法我没咋搞懂 就看明白了思路 这里贴一个答案待后续我醒悟了再来看罢 难就难在对整体数据结构classUnion&#xff08;并查集&#xff09;的理解不熟并且 对于输入输出这个迭代过程理解上也比较吃力 109. 冗余连接II 题…

【QT】QSS

个人主页~ 一、QSS QSS可以说是拿了CSS的一部分过来用&#xff0c;是CSS的简化版本 1、基本语法 选择器 {属性名:属性值; }将界面上所有的QPushButton文本颜色都改为红色 QPushButton {color:red; }2、设置方式 &#xff08;1&#xff09;指定控件样式设置 在widget.cpp中…

java模拟键盘实现selenium上下左右键 table中的左右滚动条实现滚动

在这篇文章中&#xff0c;我们将学习如何使用Java编程语言模拟键盘输入&#xff0c;特别是模拟上下左右方向键的操作。这是一个很有趣的项目&#xff0c;尤其适合刚入行的开发者。我们将分步进行&#xff0c;接下来&#xff0c;我们会通过表格展示整个实现过程&#xff0c;然后…

JQuery封装的ajax

1. 注意&#xff1a; 首先要导jq的包json对象可以用 . 来调用keyjava只能给前端传页面&#xff0c;或者打印的内容String jsonstr json.toJSONString(resultJSON); //将对象转为JSON对象 Json格式和参数解释&#xff1a; <script src"js/jquery-1.10.2.min.js&quo…