跟着GPT学设计模式之观察者模式

你好,这里是codetrend专栏“跟着GPT学设计模式”。

引言

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了对象之间的一对多依赖关系,使得当一个对象的状态发生改变时,其依赖对象都能够收到通知并自动更新。

观察者模式(Observer Design Pattern)也被称为发布订阅模式(Publish-Subscribe Design Pattern)。一般情况下,被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer)。

不过,在实际的项目开发中,这两种对象的称呼是比较灵活的,有各种不同的叫法,比如:Subject-Observer、Publisher-Subscriber、Producer-Consumer、EventEmitter-EventListener、Dispatcher-Listener。

在观察者模式中,有两个主要角色:主题(Subject)和观察者(Observer)。主题是被观察的对象,它维护了一个观察者列表,并提供方法用于添加、删除和通知观察者。

观察者是监听主题的对象,它定义了一个更新的方法,在主题状态改变时被调用。

观察者模式的一般工作流程:

  • 主题对象维护一个观察者列表,并提供方法用于注册、注销和通知观察者。
  • 观察者对象实现一个更新方法,用于在主题状态改变时被调用。
  • 当主题的状态发生改变时,它会遍历观察者列表,调用每个观察者的更新方法。
  • 观察者根据接收到的通知进行相应的操作,以使自身状态与主题保持一致。

使用 Mermaid 语法类图展示观察者模式的示意图如下:

1
*
Subject
# observers: Observer[]
+attach(Observer observer)
+detach(Observer observer)
+notifyObservers()
Observer
+update()
ConcreteSubject
- state
+getState()
+setState(state)
ConcreteObserver
+update()
  • Subject 是主题类,包含了添加、删除和通知观察者的方法。observers 是一个观察者列表,用于存储注册的观察者对象。
  • Observer 是观察者类,定义了一个 update() 方法,用于在主题状态改变时被调用。
  • ConcreteSubject 是具体主题类,继承自 Subject,它有一个额外的 state 属性,表示当前状态,并提供了获取和设置状态的方法。
  • ConcreteObserver 是具体观察者类,继承自 Observer,实现了 update() 方法,根据主题状态的改变来更新自身状态。

这个类图展示了观察者模式的关键组件及它们之间的关系。主题与观察者之间是一对多的关系,主题可以有多个观察者。

当主题状态改变时,它会通过通知方法 notifyObservers() 来遍历观察者列表,并依次调用每个观察者的 update() 方法,从而实现观察者的更新操作。

观察者模式的使用场景

观察者模式在实际应用中有很多场景,以下是一些观察者模式的应用场景的举例:

  • GUI 事件处理:在图形用户界面(GUI)中,观察者模式被广泛应用于事件处理机制。当用户执行某个操作时,比如点击按钮或输入文本,这些操作会触发相应的事件。事件作为主题被通知给注册的观察者,观察者可以根据事件类型做出相应的响应,例如更新界面、执行特定逻辑等。
  • 订阅/发布模式:观察者模式也常被称为订阅/发布模式。在发布者-订阅者系统中,发布者充当主题的角色,订阅者则扮演观察者的角色。发布者负责发布消息,订阅者订阅感兴趣的消息类型,并在消息到达时执行相应的操作。这种模式广泛应用于消息队列系统、事件总线等。
  • 消息通知系统:观察者模式也可以用于构建消息通知系统。例如,一个新闻平台可以作为主题,用户可以选择订阅感兴趣的新闻类别作为观察者。当新闻发布时,平台会通知所有订阅了该类别的用户,并将新闻推送给他们。
  • 游戏开发中的事件管理:在游戏开发中,观察者模式常被用于事件管理。例如,游戏角色之间的互动和协作可以通过观察者模式实现。一个角色可以作为主题,其他角色可以注册为观察者。当主题(例如敌人角色)发生改变时,通知所有观察者(例如友方角色)并执行相应的行为。

实际上观察者模式非常灵活,适用于很多具有发布-订阅关系的场景。它提供了一种松耦合的设计方式,使得主题和观察者能够独立变化,并保持一致性。

观察者模式使用注意事项

  • 角色和职责:观察者模式中包括主题(Subject)和观察者(Observer)两个核心角色。主题负责管理观察者的注册、注销以及通知操作,而观察者则定义了接收更新通知并执行相应操作的方法。了解每个角色的职责和关系对于正确使用观察者模式非常重要。
  • 主题状态管理:主题在观察者模式中起到承载和管理状态的作用。当主题状态发生变化时,需要通知所有观察者。因此,需要合理设计和管理主题的状态,并及时触发通知操作。
  • 多线程安全性:在多线程环境下使用观察者模式时,需要考虑线程安全性。例如,在主题状态变化时,可能会遇到多个线程同时修改主题状态或触发通知的情况。需要采取相应的同步措施或使用线程安全的容器来确保并发访问的正确性。
  • 事件传递方式:观察者模式中,主题向观察者传递更新通知的方式可以是同步或异步的。在同步方式下,主题在通知观察者后会等待观察者执行完相应操作,才会继续执行;而在异步方式下,主题通知观察者后立即继续执行,观察者的更新操作在后台进行。了解不同的事件传递方式对系统行为和性能的影响是重要的。

观察者模式编程示例

下面通过一段代码来说明观察者模式的实现。

import java.util.ArrayList;
import java.util.List;// 主题接口
interface Subject {void attach(Observer observer);void detach(Observer observer);void notifyObservers();
}// 观察者接口
interface Observer {void update();
}// 具体主题类
class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();@Overridepublic void attach(Observer observer) {observers.add(observer);}@Overridepublic void detach(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update();}}// 具体主题类的其他方法// ...
}// 具体观察者类
class ConcreteObserver implements Observer {@Overridepublic void update() {System.out.println("观察者收到更新通知,执行相应操作。");}
}public class ObserverPatternExample {public static void main(String[] args) {// 创建具体主题对象ConcreteSubject subject = new ConcreteSubject();// 创建具体观察者对象ConcreteObserver observer1 = new ConcreteObserver();ConcreteObserver observer2 = new ConcreteObserver();// 注册观察者subject.attach(observer1);subject.attach(observer2);// 主题发生改变时,通知观察者subject.notifyObservers();}
}

在上述示例中定义了一个 Subject 接口和一个 Observer 接口,分别表示主题和观察者。

ConcreteSubject 是具体的主题类,实现了 Subject 接口,并包含了维护观察者列表、添加/删除观察者以及通知观察者的方法。

ConcreteObserver 是具体的观察者类,实现了 Observer 接口,并在 update() 方法中定义了观察者接收到更新通知时的操作。

在 main() 方法中创建了具体的主题对象 ConcreteSubject,以及两个具体的观察者对象 observer1 和 observer2。

然后通过 attach() 方法将观察者注册到主题中,然后调用 notifyObservers() 方法通知所有的观察者。当主题发生改变时,所有观察者都会收到更新通知,并执行相应的操作。

以上内容基于 GPT 创建和整理。

关于作者

来自一线全栈程序员nine的探索与实践,持续迭代中。

欢迎关注或者点个赞~

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

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

相关文章

PostgreSql常用的时间类型以及对应Java中的类型以及在Mybatis XML中转换

PGSQL DATE&#xff1a;用于存储日期信息&#xff0c;不包含任何时间信息&#xff0c;例如&#xff1a;‘2024-06-06’。 TIME&#xff1a;用于存储一天内的时间&#xff0c;精确到毫秒&#xff0c;例如&#xff1a;‘10:30:00.123’。 TIMESTAMP&#xff1a;用于存储日期和…

Junit(Java单元测试)

配置文件 要想使用 Junit 进行单元测试需要引入以下第三方库&#xff1a; 引入后可以使用 Test&#xff0c;BeforeEach等注解 <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --><dependency><groupId>org.junit.jupiter<…

eclipse添加maven插件

打开eclipse菜单 Help/Install New SoftwareWork with下拉菜单选择 2022-03 - https://download.eclipse.org/releases/2022-03‘type filter text’搜索框中输入 maven选择 M2E - Maven Integration for Eclipse一路next安装&#xff0c;重启eclipseImport项目时&#xff0c;就…

ESP8266在阿里云上线(arduino)

电脑连接上ESP8266的板子 在arduino编写代码&#xff08;arduino按照之前的配置&#xff0c;已安装好esp的开发板和几个库ArduinoJson我选了5.的版本&#xff0c;PubSubclient,Crypto,AliyunIoTSDK并且修改pubsubclient的参数&#xff09; 在项目&#xff0c;加载库&#xff0c…

Elixir学习笔记——二进制、字符串和字符列表

在“基本类型”中&#xff0c;我们学习了一些关于字符串的知识&#xff0c;并使用 is_binary/1 函数进行检查&#xff1a; iex>string "hello" "hello" iex>is_binary(string) true 在本章中&#xff0c;我们将明确二进制到底是什么、它们与字符串…

【RuoYi】如何解决Postman无法访问RuoYi中的接口数据

一、前言 最近&#xff0c;写项目要求需要将数据返回&#xff0c;指定的接口&#xff0c;并且需要使用Postman来测试接口数据&#xff0c;看是否能够请求到数据。然后项目用的是RuoYi的框架&#xff0c;RuoYi使用了SpringSecurity来做的安全框架&#xff0c;所以在访问的时候&a…

【Linux】ip命令详解

Linux网络排查 目录 一、ip命令介绍 1.1 ip命令简介 1.2 ip命令的由来 二、ip命令使用帮助 2.1 ip命令的help帮助信息 2.2 ip命令对象介绍 2.3 ip命令选项介绍 三、查看网络信息 3.1 显示当前网络接口信息 3.2 显示网络设备运行状态 3.3 显示详细设备信息 3.4 查看…

基于.NetCore和ABP.VNext的项目实战八:使用Redis缓存数据

这里将集成Redis,使用Redis来缓存数据,在appsettings.json配置Redis的连接字符串 //appsettings.json ..."Caching": {"IsOpen": "true","RedisConnectionString": "127.0.0.1:6379,ConnectTimeout=15000,SyncTimeout=5000&qu…

面向大模型的存储加速方案

参考&#xff1a;面向大模型的存储加速方案设计和实践-百度开发者中心 (baidu.com) 对于一个典型的训练来说&#xff0c;可能迭代多轮 epoch。在每个 epoch 内&#xff0c;首先需要对数据集进行随机打散&#xff0c;然后将打散后的数据划分为若干 batch&#xff0c;每读取一个 …

智谱AI最新开源模型CHATGLM4-9B试用

智谱AI最近开源了GLM4-9B模型。之前已开源chatglm1到chatglm3&#xff0c;相比前面开源的相比GLM3-6B有了大幅度提升。本次开源基本的GLM4-9B&#xff0c;还开源了对话版GLM-4-9B-Chat&#xff0c; 多模态版GLM-4V-9B&#xff0c; 长文本版GLM-4-9B-Chat-1M。 在语义、数学、推…

软件杯 题目:基于深度学习卷积神经网络的花卉识别 - 深度学习 机器视觉

文章目录 0 前言1 项目背景2 花卉识别的基本原理3 算法实现3.1 预处理3.2 特征提取和选择3.3 分类器设计和决策3.4 卷积神经网络基本原理 4 算法实现4.1 花卉图像数据4.2 模块组成 5 项目执行结果6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基…

Nginx location 配置:从入门到精通

Nginx的 location 配置是Nginx服务器配置中非常关键的一部分&#xff0c;它决定了如何响应不同的HTTP请求。以下是关于Nginx location配置的详细解释&#xff1a; 一、基本语法 location指令的基本语法如下&#xff1a; location [modifier] pattern {# 配置内容 }其中&#…

零拷贝技术

背景 磁盘可以说是计算机系统重最慢的硬件之一&#xff0c;读写速度相对内存10以上&#xff0c;所以针对优化磁盘的技术非常的多&#xff0c;比如&#xff1a;零拷贝、直接I/O、异步I/O等等&#xff0c;这些优化的目的就是为了提高系统的吞吐量&#xff0c;另外操作系统内核中的…

如何实现观察者模式和发布-订阅模式?

要实现观察者模式和发布-订阅模式&#xff0c;你需要遵循一些基本的步骤和原则。下面分别介绍这两种模式的实现方法。 如何实现观察者模式&#xff1a; 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为设计模式&#xff0c;用于维护观察者&#xff08;Observe…

GAT1399协议分析(8)--ImageInfo字段详解

一、官方定义 接上一章节字段消息返回内容 "ImageInfo": { "ImageID": "34078100001190001002012024060513561300065", "InfoKind": 0, "ImageSource": "…

eclipse怎么导入python项目

python项目导入eclipse的步骤&#xff1a; 1、首先&#xff0c;打开Eclipse集成开发程序&#xff0c;在菜单栏上点击“File(F)”&#xff0c;在弹出来的列表中点击“导入&#xff08;I&#xff09;...”。 2、在弹出来的“导入”窗口中&#xff0c;选择“常规”选项中的“现有…

【uni-app】开发问题汇总

文章目录 1、APP获取dom2、添加页面&#xff0c;参考其他页面&#xff0c;国际化就是对应页面的导航的国际化"navigationBarTitleText": "%m.i.ForgetPaymentPassword.bartitle%",3、setStatusBarStyle这个导航栏设置方法不要了&#xff0c;导航栏现在都用…

SpringCloud Gateway中Filters详细说明

前面 https://blog.csdn.net/J080624/article/details/139494909 我们研究了GateWay中各种路由断言的使用。SpringCloud GateWay 还提供了各种过滤器用来对请求和响应进行处理。 官网地址&#xff1a;SpringCloud Gateway Filter 【1】GatewayFilter Factories 路由过滤器允…

java使用websocket遇到的问题

java使用websocket的bug 1 websocket连接正常但是收不到服务端发出的消息java的websocket并发的时候导致连接断开&#xff08;看着连接是正常的&#xff0c;但是实际上已经断开&#xff09; 1 websocket连接正常但是收不到服务端发出的消息 java的websocket并发的时候导致连接断…

oracle中varchar和varchar2的区别

在Oracle数据库中&#xff0c;VARCHAR和VARCHAR2都是用于存储可变长度字符数据的数据类型&#xff0c;但它们之间有一些关键的区别。以下是这两者的主要区别&#xff1a; 数据类型来源&#xff1a; VARCHAR&#xff1a;这是标准SQL提供的类型&#xff0c;具有广泛的数据库系统…