设计模式二十:观察者模式(Observer Pattern)
定义了一种一对多的依赖关系,允许多个观察者(也称为订阅者)对象同时监听一个主题对象,当主题对象发生变化时,所有依赖于它的观察者都会收到通知并自动更新。
观察者模式的使用场景
观察者模式在许多场景中都可以发挥作用,特别是在需要解耦和实现对象间动态通信的情况下
- 事件处理和 GUI:
在图形用户界面(GUI)应用中,用户界面元素(如按钮、文本框)可以作为观察者,而事件(如点击按钮)可以作为主题,以实现用户界面与业务逻辑之间的解耦。 - 订阅/发布模型:
观察者模式常被用于实现发布/订阅模型,其中发布者是主题,订阅者是观察者。这在消息队列系统、事件总线等场景中非常有用,允许消息的生产者发布消息,而消费者订阅并处理消息。 - 通知和提醒系统:
观察者模式可以用于实现通知和提醒系统。例如,在一个新闻网站中,当有新的新闻发布时,订阅了该类新闻的用户会收到通知。 - 股票市场分析:
在金融领域,观察者模式可以用于股票市场分析工具。股票价格的变化可以作为主题,不同的分析器可以作为观察者,以便在价格变化时及时更新分析结果。 - 网络应用中的状态同步:
在分布式系统或网络应用中,观察者模式可以用于状态同步。当一个节点的状态发生变化时,其他节点可以作为观察者,以便实时更新其本地状态。 - 游戏开发:
在游戏开发中,观察者模式可以用于处理游戏内的事件、状态变化、角色行为等。例如,当一个角色受到伤害时,其他角色可以作为观察者获得相应的通知。 - 传感器数据监测:
在物联网领域,传感器收集到的数据可以作为主题,不同的监测系统可以作为观察者,以便在数据变化时进行监测和报警。
观察者模式涉及的角色
- 主题(Subject):
主题是被观察的对象,它维护一组观察者对象,并提供方法用于添加、删除和通知观察者。主题通常包含状态或数据,当状态变化时会通知所有观察者。
定义了添加、删除和通知观察者的方法。
维护一个观察者列表,用于存储注册的观察者。
当主题状态变化时,调用通知方法以便通知所有注册的观察者。 - 具体主题(Concrete Subject):
具体主题是实际的被观察对象,它继承或实现主题接口,负责实现主题的具体逻辑。它会在状态变化时通知所有已注册的观察者。
继承或实现主题接口。
包含需要被观察的状态或数据。
在状态变化时,调用通知方法来通知所有观察者。 - 观察者(Observer):
观察者是订阅主题状态变化的对象,它定义一个更新方法,当主题状态发生变化时,观察者的更新方法会被调用,从而观察者可以获取最新的信息并执行相应的操作。
定义了一个更新方法,用于在主题状态变化时被调用。
观察者通过该方法获取主题最新的状态信息,然后执行相应的操作。 - 具体观察者(Concrete Observer):
具体观察者是实际的观察者对象,它实现了观察者接口的更新方法,以便在主题状态变化时执行特定的操作。
实现观察者接口的更新方法,以便在主题状态变化时执行具体的操作。
在更新方法中,根据主题的状态变化来做出响应。
java代码实例
演示了使用观察者模式实现一个天气预报系统
主题接口
package cn.observer.service;public interface Subject {//添加接受这void addObserver(Observer_ observer);//一处接受者void reduceObserver(Observer_ observer);//消息变动void notifyObservers();}
具体主题
//天气驿站
public class WeatherStation implements Subject{private List<Observer_> observers=new ArrayList<>();private float temperature;//天气温度@Overridepublic void addObserver(Observer_ observer) {this.observers.add(observer);}@Overridepublic void reduceObserver(Observer_ observer) {this.observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer_ observer: observers) {observer.recept(this.temperature);}}public void setTemperature(float temperature) {this.temperature = temperature;notifyObservers();}}
观察者接口
//天气广播台public interface Observer_ {void recept(float temperature);}
具体观察者
public class WeatherDisplay implements Observer_{@Override public void recept(float temperature) {System.out.println("当前温度:"+temperature+"度"); }
}
客户端
public class Observer {public static void main(String[] args) {WeatherStation station = new WeatherStation();WeatherDisplay display = new WeatherDisplay();station.addObserver(display);station.setTemperature(25.5f);station.reduceObserver(display);station.setTemperature(30.0f); }}
输出结果
当前温度:25.5度
观察者模式的优缺点
优点:
- 解耦性:
观察者模式可以将主题对象与观察者对象之间的依赖关系解耦,使它们可以独立变化,不会相互影响。 - 灵活性和可扩展性:
由于主题和观察者之间的关系是松耦合的,可以轻松添加新的观察者或修改现有的观察者,而不需要修改主题。 - 一对多通信:
观察者模式允许一个主题同时通知多个观察者,这在实现发布/订阅模型、事件处理和消息传递等场景中非常有用。 - 可维护性:
观察者模式使系统中的各个部分更容易理解和维护,因为它将复杂的交互逻辑分解为独立的观察者对象。 - 支持动态添加和移除观察者:
可以动态地注册和注销观察者,使系统更加灵活。
缺点:
- 内存泄漏:
如果观察者没有正确注销,它们仍然会保留对主题的引用,可能导致内存泄漏。 - 不当使用带来复杂性:
过多或不合理地使用观察者模式可能会导致系统复杂化,降低可维护性。因此,在设计时需要权衡使用。 - 顺序问题:
观察者模式中观察者的通知顺序是不确定的,这可能导致一些问题,特别是在观察者之间有相互依赖关系时。 - 性能问题:
当观察者数量庞大且通知频繁时,可能会影响性能。因此,在高性能要求的系统中需要谨慎使用。
相关文章:
设计模式二十:观察者模式(Observer Pattern)
定义了一种一对多的依赖关系,允许多个观察者(也称为订阅者)对象同时监听一个主题对象,当主题对象发生变化时,所有依赖于它的观察者都会收到通知并自动更新。 观察者模式的使用场景 观察者模式在许多场景中都可以发挥…...
Linux操作系统--CentOS使用初体验
我们安装好Linux的操作系统之后,下面就可以使用Linux操作系统了。我们一起来看看如何使用。 (1).桌面 我们在进入CentOS操作系统后可以发现一些和Windows操作系统相类似的情况。如:网络、时间显示、以及基本的软件等内容。 --创建文件、文件夹。 (2).操作终端 Linux中的终…...
搭建HAProxy + Keepalived高可用
安装 在四台虚拟机上,我们以如下方式搭建集群: 192.168.115.3 haproxykeepalived 192.168.115.4haproxykeepalived 192.168.115.5 nginx 192.168.115.6 nginx 在192.168.115.3 和192.168.115.4 上安装haproxy和keepalived(haproxy编译安装…...
使用Python爬虫定制化开发自己需要的数据集
在数据驱动的时代,获取准确、丰富的数据对于许多项目和业务至关重要。本文将介绍如何使用Python爬虫进行定制化开发,以满足个性化的数据需求,帮助你构建自己需要的数据集,为数据分析和应用提供有力支持。 1.确定数据需求和采集目…...
java八股文面试[java基础]——接口和抽象类的区别
知识来源: 【基础】接口和抽象类_哔哩哔哩_bilibili 【2023年面试】Java中抽象类和接口有什么区别_哔哩哔哩_bilibili 【23版面试突击】抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口么?_…...
head 请求了解过吗?如何用 get 模拟 head 请求?不需要服务器返回数据,怎么实现?
HEAD请求是HTTP/1.1协议中定义的一个请求方法,与GET请求相似,但只请求目标URL的头部,不请求实际的数据或者说正文内容。其主要用途是: 检查资源是否存在。获取资源的元数据(如响应头中的Content-Length或Last-Modifie…...
Redis笔记——(狂神说)待续
Nosql概述 为什么要用NoSql? 1、单机mysql的年代:90年代,网站访问量小,很多使用静态网页html写的,服务器没压力。 当时瓶颈是:1)数据量太大一个机器放不下。2)数据的索引(BTree),一个机器内存也…...
基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v7.0版已发布
关于MobileIMSDK MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架,超轻量级、高度提炼,一套API优雅支持 UDP 、TCP 、WebSocket 三种协议,支持 iOS、Android、H5、标准Java、小程序、Uniapp,服务端基于Netty编写。 工程…...
BLFS学习系列 第26章. 显示管理器 —— 总述
显示管理器(Display Manager)是用于启动图形显示(当前为X服务器)并为窗口管理器或桌面环境提供登录功能的图形程序。 有许多显示管理器可用。一些较为知名的包括:GDM、KDM(已弃用)、LightDM、L…...
macOS上编译obs-studio
前言 最近基于obs的1个二开程序,需要移植到macOS平台上,由于遇到些问题,本文记录下如何在macOS上配置&编译&运行obs程序完整过程。 下载 首先下载cmake-gui工具,下载CMAKE,选择对应macOS平台的cmake版本&…...
Oracle数据库快速入门
前言: 我想现在很多人的入门数据库都是mysql,但是由于工作中会接触到Oracle数据库,如果你有MySQL的基础的话,这篇文章能让你很快掌握Oracle。 目录 1.体系结构 2.创建用户和表空间 2.1.创建表空间 2.2.创建用户 3.数据类型…...
Linux内核学习(十)—— 块 I/O 层(基于Linux 2.6内核)
目录 一、剖析一个块设备 二、缓冲区和缓冲区头 三、bio 结构体 四、请求队列 五、I/O 调度程序 系统中能够随机(不需要按顺序)访问固定大小数据片(chunks)的硬件设备称作块设备,这些固定大小的数据片就称作块。最…...
SpringMVC 写个 HelloWorld
文章目录 一、SpringMVC简介1、什么是MVC2、什么是SpringMVC3、SpringMVC的特点 二、HelloWorld1、开发环境2、创建maven工程a>添加web模块b>打包方式:warc>引入依赖 3、配置web.xmla>默认配置方式b>扩展配置方式 4、创建请求控制器5、创建springMVC…...
ARM--day7(cortex_M4核LED实验流程、异常源、异常处理模式、异常向量表、异常处理流程、软中断编程、cortex_A7核中断实验)
软中断代码:(keil软件) .text .global _start _start:1.构建异常向量表b resetb undef_interruptb software_interruptb prefetch_dataabortb data_abortb .b irqb fiq reset:2.系统一上电,程序运行在SVC模式1>>初始化SVC模…...
Java中LinkList的基本介绍和细节讨论。双向链表的代码和LinkList的源码。LinkList和ArrayList的比较与选择。
LinkedList 是 Java 中的一个双向链表实现的类,它实现了 List 接口,同时也实现了 Deque 接口,因此可以用作列表、队列或双端队列。下面是关于 LinkedList 的基本介绍和细节讨论: 基本介绍: LinkedList 是一个双向链表…...
Proteus软件安装包分享(附安装教程)
目录 一、软件简介 二、软件下载 一、软件简介 Proteus软件是一款电路设计和仿真的综合性软件,由Labcenter公司开发。它提供了一个交互式的图形界面,用户可以在其中构建电路、仿真结果并实时观察仿真结果。 1、Proteus的历史和演变 Proteus软件最初于…...
“图为科技——什么是边缘计算“
边缘计算是一种新兴的计算模式,它将计算资源和服务推向离终端设备更近的地方。以往,计算任务大多集中在云端进行,但随着物联网和移动互联网的快速发展,边缘计算应运而生。 边缘计算的核心思想是将计算、存储和网络功能部署在离终端…...
SpringCloud教程 | 第六篇: 分布式配置中心(Spring Cloud Config)
在上一篇文章讲述zuul的时候,已经提到过,使用配置服务来保存各个服务的配置文件。它就是Spring Cloud Config。 一、简介 在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需…...
mysql 错误码
一、 #22001 Caused by: java.sql.BatchUpdateException: Data truncation: #22001检查一下数据库表字段,特别是VARCHAR的长度是否够。 Caused by: java.sql.BatchUpdateException: #HY000检查是不是违反了非空约束,NOT NULL字段有没有没传的 二、...
HTML的form表单标签详解~
通过HTML提交表单数据有web中是非常常用的操作,所以有必要详细、仔细学习了解HTML的form表单。 目录 01-关键词 novalidate 是什么意思?02- action"" 是什么意思?03- enctype"multipart/form-data" 是什么意思࿱…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
