【设计模式】JAVA Design Patterns——Observer(观察者模式)

🔍目的


定义一种一对多的对象依赖关系这样当一个对象改变状态时,所有依赖它的对象都将自动通知或更新。

🔍解释


真实世界例子

在遥远的土地上生活着霍比特人和兽人的种族。他们都是户外生活的人所以他们密切关注天气的变化。可以说他们不断地关注着天气。

通俗描述

注册成为一个观察者以接收对象状态的改变。

维基百科

观察者模式是这样的一种软件设计模式:它有一个被称为主题的对象,维护着一个所有依赖于它的依赖者清单,也就是观察者清单,当主题的状态发生改变时,主题通常会调用观察者的方法来自动通知观察者们。

编程示例

首先创建天气观察者的接口以及我们的种族,兽人和霍比特人。

public interface WeatherObserver {void update(WeatherType currentWeather);
}@Slf4j
public class Orcs implements WeatherObserver {@Overridepublic void update(WeatherType currentWeather) {LOGGER.info("The orcs are facing " + currentWeather.getDescription() + " weather now");}
}@Slf4j
public class Hobbits implements WeatherObserver {@Overridepublic void update(WeatherType currentWeather) {switch (currentWeather) {LOGGER.info("The hobbits are facing " + currentWeather.getDescription() + " weather now");}
}

创建一个动态变化的天气:

@Slf4j
public class Weather {private WeatherType currentWeather;private final List<WeatherObserver> observers;public Weather() {observers = new ArrayList<>();currentWeather = WeatherType.SUNNY;}public void addObserver(WeatherObserver obs) {observers.add(obs);}public void removeObserver(WeatherObserver obs) {observers.remove(obs);}/*** Makes time pass for weather.*/public void timePasses() {var enumValues = WeatherType.values();currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];LOGGER.info("The weather changed to {}.", currentWeather);notifyObservers();}private void notifyObservers() {for (var obs : observers) {obs.update(currentWeather);}}
}

执行示例:

    var weather = new Weather();weather.addObserver(new Orcs());weather.addObserver(new Hobbits());weather.timePasses();// The weather changed to rainy.// The orcs are facing rainy weather now// The hobbits are facing rainy weather nowweather.timePasses();// The weather changed to windy.// The orcs are facing windy weather now// The hobbits are facing windy weather nowweather.timePasses();// The weather changed to cold.// The orcs are facing cold weather now// The hobbits are facing cold weather nowweather.timePasses();// The weather changed to sunny.// The orcs are facing sunny weather now// The hobbits are facing sunny weather now

🔍类图


🔍扩展延伸 

观察者模式在kafka client consumer中的使用:

大致逻辑

consumer想要消费kafka broker中的数据需要发送request,request发送的结果用RequestFuture来表示,RequestFuture中包含RequestFutureListener,当request处理完成后RequestFutureListener的相关方法会被调用。RequestFutureCompletionHandler用来处理RequestFuture、ClientResponse还有RuntimeException。

依赖关系:

RequestFutureListener为观察者,onSuccess和onFail方法相当于之前的update方法;RequestFuture为被观察者,addListener相当于attach方法,fireSuccess和fireFailure方法相当于notify方法。

RequestFutureListener部分代码:
public interface RequestFutureListener<T> {void onSuccess(T value);void onFailure(RuntimeException e);
}
RequestFuture部分代码: 
public class RequestFuture<T> implements ConsumerNetworkClient.PollCondition {private static final Object INCOMPLETE_SENTINEL = new Object();private final AtomicReference<Object> result = new AtomicReference<>(INCOMPLETE_SENTINEL);private final ConcurrentLinkedQueue<RequestFutureListener<T>> listeners = new ConcurrentLinkedQueue<>();private final CountDownLatch completedLatch = new CountDownLatch(1);public void complete(T value) {try {if (value instanceof RuntimeException)throw new IllegalArgumentException("The argument to complete can not be an instance of RuntimeException");if (!result.compareAndSet(INCOMPLETE_SENTINEL, value))throw new IllegalStateException("Invalid attempt to complete a request future which is already complete");fireSuccess();} finally {completedLatch.countDown();}}
//遍历listener并调用其success时的方法private void fireSuccess() {T value = value();while (true) {RequestFutureListener<T> listener = listeners.poll();if (listener == null)break;listener.onSuccess(value);}}
//遍历listener并调用其fail时的方法private void fireFailure() {RuntimeException exception = exception();while (true) {RequestFutureListener<T> listener = listeners.poll();if (listener == null)break;listener.onFailure(exception);}}//增加listenerpublic void addListener(RequestFutureListener<T> listener) {this.listeners.add(listener);if (failed())fireFailure();else if (succeeded())fireSuccess();}

🔍适用场景


在下面任何一种情况下都可以使用观察者模式

  • 当抽象具有两个方面时,一个方面依赖于另一个方面。将这些方面封装在单独的对象中,可以使你分别进行更改和重用
  • 当一个对象的改变的同时需要改变其他对象,同时你又不知道有多少对象需要改变时
  • 当一个对象可以通知其他对象而无需假设这些对象是谁时。换句话说,你不想让这些对象紧耦合。

🔍Ending


观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。

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

  1. 主题(Subject):被观察的对象,它会维护一组观察者对象,并在自身状态发生变化时通知观察者。
  2. 观察者(Observer):观察主题对象的状态变化,并根据变化做出相应的动作。
  3. 具体主题(ConcreteSubject):实现了主题接口的具体对象,负责维护观察者列表,并在自身状态发生变化时通知观察者。
  4. 具体观察者(ConcreteObserver):实现了观察者接口的具体对象,负责接收主题对象的通知,并根据通知更新自身状态。

希望本文能够帮助读者更深入地理解观察者模式,并在实际项目中发挥其优势。谢谢阅读!


希望这份博客草稿能够帮助到你。如果有其他需要修改或添加的地方,请随时告诉我。

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

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

相关文章

计算机专业本科就业还是考研?考研有哪些热门方向?

考研并不是一个逃避就业的避难所&#xff0c;也不是一个简单的提升待遇的手段。考研是提升自我的途径&#xff0c;特别是对于那些对特定技术领域有浓厚兴趣并愿意深入研究的人来说 一个本科生能够认真学三年&#xff0c;那么他们所掌握的技能和知识不应该逊色于那些通过短期培…

【面试干货】 非关系型数据库(NoSQL)与 关系型数据库(RDBMS)的比较

【面试干货】 非关系型数据库&#xff08;NoSQL&#xff09;与 关系型数据库&#xff08;RDBMS&#xff09;的比较 一、引言二、非关系型数据库&#xff08;NoSQL&#xff09;2.1 优势 三、关系型数据库&#xff08;RDBMS&#xff09;3.1 优势 四、结论 &#x1f496;The Begin…

jupyter notebook anaconda环境下查看|加载|更换内核

文章目录 1 问题复现2 查看内核位置3 调整python解释器位置 1 问题复现 在conda虚拟环境中使用pip安装相应package&#xff0c; 但是在jupyter notebook中加载该package时报错 [ERROR]ModuleNotFoundError: No module named shap 此时&#xff0c;除去包安装出现问题以外&am…

BIOS主板(非UEFI)安装fedora40的方法

BIOS主板(非UEFI)安装fedora40的方法 现实困难&#xff1a;将Fedora-Workstation-Live-x86_64-40-1.14.iso写入U盘制作成可启动U盘启动fedora40&#xff0c;按照向导将fedora40安装到真机的sda7分区中得到报错如下内容&#xff1a; Failed to find a suitable stage1 device: E…

socket网络编程——套接字地址结构

一、通用 socket 地址结构 socket 网络编程接口中表示 socket 地址的是结构体 sockaddr&#xff0c;其定义如下&#xff1a; 1. #include <bits/socket.h> 2. 3. struct sockaddr 4. { 5. sa_family_t sa_family; 6. char sa_data[14]; 7. }; sa_family 成员是地址族类型…

【Java数据结构】详解Stack与Queue(四)

&#x1f512;文章目录&#xff1a; 1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; 2.用队列实现栈 3.用栈实现队列 4.栈和队列存放null 5.总结 1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友…

LVS精益价值管理系统 LVS.Web.ashx SQL注入漏洞复现

0x01 产品简介 LVS精益价值管理系统是杭州吉拉科技有限公司研发的一款专注于企业精益化管理和价值流优化的解决方案。该系统通过集成先进的数据分析工具、可视化的价值流映射技术和灵活的流程改善机制,帮助企业实现高效、低耗、高质量的生产和服务。 0x02 漏洞概述 LVS精益…

python下用cartopy绘制地形晕染(shading)图

python可以利用rasterio&#xff0c;cartopy&#xff0c;matplotlib等库绘制地形晕染图。 1.获取高程数据 高程数据可以从GEBCO网站下载&#xff1a;&#xff08;https://www.gebco.net/data_and_products/gridded_bathymetry_data/&#xff09;。 选择raster&#xff08;栅…

如何在自己的电脑上添加静态路由

1.任务栏搜索powershell 选择以管理员身份运行 2.输入 route add -p (永久) 目的网络地址例如192.168.10.0 mask 255.255.255.0&#xff08;子网掩码&#xff09;192.168.20.1&#xff08;下一跳地址&#xff09;。回车即可生效

性能测试学习-基本使用-元件组件介绍(二)

jmeter优点是&#xff1a;开源免费&#xff0c;小巧&#xff0c;丰富的学习资料和扩展组件 缺点是&#xff1a;1.不支持IP欺骗&#xff0c;分析和报表能力相对于LR欠缺精确度&#xff08;以分钟为单位&#xff09; 工具用户量分析报表IP欺骗费用体积扩展性Loadrunner多(万)精…

day4 数1 隐函数

基础知识 隐函数 &#xff1a;一个方程里边 使x有1个y与之对应 函数的有界性 f(X) 的值大于-M并小于M 单调性 可以用定义发判断单调性 定义法 奇函数 奇函数关于原点对称&#xff0c;偶关于x对称 定义域要关于原点对称 任何一个函数可以写成奇函数偶函数的形式 复合函数的…

【MySQL】MySQL 图形化界面 - 使用说明(MySQL Workbench)

一、安装软件 Navicat&#xff0c;SQLyog 这些软件都不错&#xff0c;不过都需要收费&#xff0c;当然也有破解版。下面用 MySQL Workbench&#xff0c;它是官方提供的工具。 二、使用操作 这个软件本质是一个客户端&#xff0c;现在要让数据库能够远程登录。不过一般不会远程…

SPME2024开幕在即,深兰科技商用清洁机器人新品推介会蓄势待发

6月5日&#xff5e;7日&#xff0c;以“跨界融合洞见未来”为主题的“2024 SPME第六届上海国际物业管理产业博览会”(以下简称“物博会”)将在上海世博展览馆举行。应主办方邀请&#xff0c;深兰科技携多款AI清洁机器人亮相本届展会&#xff0c;向来自全球各地的观展企业家、经…

C++第二十三弹---深入理解STL中list的使用

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、list的介绍 2、list的使用 2.1、构造函数 2.2、赋值操作符重载 2.3、迭代器使用 2.4、容量操作 2.5、元素访问 2.6、修改操作 2.7、其…

Docker 环境下 3D Guassian Splatting 的编译和配置

Title: Docker 环境下 3D Guassian Splatting 的编译和配置 文章目录 前言I. 宿主系统上的安装配置1. 安装 nvidia driver2. 安装 docker3. 安装 nvidia-container-toolkit II. Docker 容器安装配置1. 拉取 ubuntu 22.042. 创建容器3. 进入容器4. 容器中安装 cuda SDK5. 容器中…

详解和实现数据表格中的行数据合并功能

theme: smartblue 前言 需求场景&#xff1a; 在提供了数据查看和修改的表格视图中(如table、a-table等…)&#xff0c;允许用户自行选择多行数据&#xff0c;依据当前状态进行特定列数据的合并操作。选中的数据将统一显示为选中组的首条数据值。同时&#xff0c;页面会即时反…

FASTGPT:可视化开发、运营和使用的AI原生应用

近年来&#xff0c;随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;AI的应用逐渐渗透到各行各业。作为一种全新的开发模式&#xff0c;AI原生应用正逐步成为行业的焦点。在这方面&#xff0c;FASTGPT无疑是一款颇具代表性的产品。本文将详细介绍FASTGPT的设…

使用compile_commands.json配置includePath环境,解决vscode中引入头文件处有波浪线的问题

通过编译时生成的 compile_commands.json 文件自动完成对 vscode 中头文件路径的配置&#xff0c;实现 vscode 中的代码的自动跳转。完成头文件路径配置后&#xff0c;可以避免代码头部导入头文件部分出现波浪线&#xff0c;警告说无法正确找到头文件。 步骤 需要在 vscode 中…

k8s怎么监听资源的变更

监听k8s所有的 Deployment 资源 package mainimport ("context""fmt"v1 "k8s.io/api/apps/v1""k8s.io/apimachinery/pkg/util/json""k8s.io/client-go/informers""k8s.io/client-go/kubernetes""k8s.io/cli…

顺序表的讲解与实现

顺序表的讲解与实现 一、顺序表的概念及结构二、顺序表分类(C语言实现)顺序表和数组的区别顺序表分类静态顺序表动态顺序表 三、动态顺序表的实现(使用VS2022)1.初始化、销毁、打印内容2.检查扩容3.尾部插入、尾部删除、头部插入、头部删除尾部插入尾部删除头部插入头部删除 4.…