【设计模式】聊聊观察者设计模式原理及应用

原理

观察者模式属于行为模式,行为模式主要解决类和对象之间交互问题。
含义:在对象之间定义一个一对多的依赖,当一个对象状态改变时,所有依赖的对象会自动通知。

被依赖的对象被观察者(Observable) ,依赖的对象观察者(Observer),当然也可以叫发布-订阅等。
在这里插入图片描述

一个case

比如我们维护的用户中心,当用户进行注册的时候,就进行通知发送短信、WA、邮件等。

1.第一步,先定义被观察者接口,主要就是注册、删除、已经通知观察者。

/*** @author qxlx* @date 2024/4/13 22:25*/
public interface Subject {/*** 注册* @param observer*/void registerObserver(Observer observer);/*** 删除* @param observer*/void deleteObserver(Observer observer);/*** 发送事件* @param message*/void notifyObservers(String message);
}

2.定义贯彻者具体的行为

public interface Observer {void notify(String message);}

3.被观察者的具体实现,可以发送通过接口注册或删除观察者,当被观察者执行用户注册的方法时,就会触发通知观察者进行处理。
这里需要明确下,可以采用同步的方式 或者异步方式。因为对于注册接口来说响应时间还是比较重要的,采用线程的方式 可以提高接口性能。

/*** @author qxlx* @date 2024/4/13 22:27*/
public class ConcreteSubject implements Subject {private List<Observer> observerList = new CopyOnWriteArrayList<>();@Overridepublic void registerObserver(Observer observer) {observerList.add(observer);}@Overridepublic void deleteObserver(Observer observer) {observerList.remove(observer);}@Overridepublic void notifyObservers(String message) {// 1.同步调用// 2.异步非阻塞observerList.forEach(o -> o.notify(message));// new Thread()new Thread(() -> {observerList.forEach(o -> o.notify(message));}).start();// 线程池ThreadPoolUtil.getThreadPool(10).execute(() -> observerList.forEach(o -> o.notify(message)));}
}

4.定义具体的观察者实现类,发送邮件 或者发送wa

public class UserSendEmailObserver implements Observer{@Overridepublic void notify(String message) {System.out.println("用户注册成功,发送邮件通知!");}}public class UserWaSendObserver implements Observer{@Overridepublic void notify(String message) {System.out.println("用户注册成功,发送了wa通知");}
}

最终的Demo 其实就是这样,将观察者添加到被观察者上,观察者一旦执行了用户注册,就会触发对应动作,比如说新增新的动作,那么就可以直接添加一个发优惠卷的观察者。可以很好的进行拓展。

    public static void main(String[] args) {UserSendEmailObserver userSendEmailObserver = new UserSendEmailObserver();UserWaSendObserver userWaSendObserver = new UserWaSendObserver();ConcreteSubject concreteSubject = new ConcreteSubject();concreteSubject.registerObserver(userSendEmailObserver);concreteSubject.registerObserver(userWaSendObserver);concreteSubject.notifyObservers("register");}

在这里插入图片描述

Spring 中如何应用观察者模式

在spring源码中,IOC容器进行初始化的过程中,refresh() 方法中就包含观察者模式。而Spring进行了抽象,也就是将观察者和被观察者 进行调整成多播器和监听器,通过事件来驱动监听器的执行。
在这里插入图片描述
在这里插入图片描述

可以看到,整体的流程就是,初始化多播器对象,SimpleApplicationEventMulticaster,将监听器添加到多播器中。然后发布事件,调用监听器进行处理。可以发现其实设计模式在实际的应用中,思想相同的,但是落地的时候都有自己的调整。本质上还是当多个对象所依赖的对象有对应的事件时,需要做对应的动作。解耦合观察者和被观察者。

	//初始化事件多播功能(事件派发) Initialize event multicaster for this context.//初始化多播器 SimpleApplicationEventMulticaster 注册到IOC容器中initApplicationEventMulticaster();//注册监听器,从容器中获取所有的ApplicationListener;// Check for listener beans and register them.registerListeners();//发布事件 Last step: publish corresponding event.finishRefresh();

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

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

相关文章

Go: 理解 Sync.Pool 的设计

sync 包提供了一个强大且可复用的实例池&#xff0c;以减少 GC 压力。在使用该包之前&#xff0c;我们需要在使用池之前和之后对应用程序进行基准测试。这非常重要&#xff0c;因为如果不了解它内部的工作原理&#xff0c;可能会影响性能。 池的限制 我们来看一个例子以了解它…

【电控笔记3.5】三相逆变器

基础 大小调变指标ma 频率调变指标mf 载波频率:pwm频率

日本极致产品力 | 井村屋红豆棒冰如何年销2.5亿根

《极致产品力》日本深度研学是一个顾问式课程,可以帮助企业找产品、找方向、找方法,在日本终端市场考察中洞悉热销产品背后的成功逻辑&#xff0c;了解最新最前沿的产品趋势和机会。结合日本消费趋势中国转化的众多经验,从品牌、包装、卖点、技术和生产艺等多方面寻找中国市场的…

MoCo v2 论文解读

paper&#xff1a;Improved Baselines with Momentum Contrastive Learning official implementation&#xff1a;https://github.com/facebookresearch/moco 这篇文章的内容只有2页&#xff0c;不能称之为paper&#xff0c;作者本人也称之为note。主要内容就是将SimCLR中的两…

1.5MHz,1.2A COT 架构同步降压变换器只要0.16元,型号:LN3435

推荐原因 1.5MHZ的开关频率&#xff0c;可以使用小电感&#xff0c;1.2A满足多数应用&#xff0c;价格感人&#xff0c;只要0.16元 产品概述 LN3435是一款电流模COT架构同步降压开关稳压器。 输入范围为 2.7V-6.0V&#xff0c;可提供 1.2A 的连续输出电流。 内部集成了低内阻…

学习Rust的第4天:常见编程概念

基于Steve Klabnik的《The Rust Programming Language》一书。昨天我们做了一个猜谜游戏 &#xff0c;今天我们将探讨常见的编程概念&#xff0c;例如&#xff1a; Variables 变量Constants 常数Shadowing 阴影Data Types 数据类型Functions 功能 Variables 变量 In layman ter…

C语言入门第四天(数组)

一、C语言数组的基本语法 1.数组的定义 数组是 C 语言中的一种数据结构&#xff0c;用于存储一组具有相同数据类型的数据。数组中的每个元素可以通过一个索引&#xff08;下标&#xff09;来访问&#xff0c;索引从 0 开始&#xff0c;最大值为数组长度减 1。 2.定义语法格式 …

4个步骤:如何使用 SwiftSoup 和爬虫代理获取网站视频

摘要/导言 在本文中&#xff0c;我们将探讨如何使用 SwiftSoup 库和爬虫代理技术来获取网站上的视频资源。我们将介绍一种简洁、可靠的方法&#xff0c;以及实现这一目标所需的步骤。 背景/引言 随着互联网的迅速发展&#xff0c;爬虫技术在今天的数字世界中扮演着越来越重要…

Python也可以合并和拆分PDF,批量高效!

PDF是最方便的文档格式&#xff0c;可以在任何设备原样且无损的打开&#xff0c;但因为PDF不可编辑&#xff0c;所以很难去拆分合并。 知乎上也有人问&#xff0c;如何对PDF进行合并和拆分&#xff1f; 看很多回答推荐了各种PDF编辑器或者网站&#xff0c;确实方法比较多。 …

支持向量机模型pytorch

通过5个条件判定一件事情是否会发生&#xff0c;5个条件对这件事情是否发生的影响力不同&#xff0c;计算每个条件对这件事情发生的影响力多大&#xff0c;写一个支持向量机模型pytorch程序,最后打印5个条件分别的影响力。 示例一 支持向量机&#xff08;SVM&#xff09;是一种…

【原创】springboot+mysql理发会员管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

算法课程笔记——常用库函数

memset初始化 设置成0是可以每个设置为0 而1时会特别大 -1的补码是11111111 要先排序 unique得到的是地址 地址减去得到下标 结果会放到后面 如果这样非相邻 会出错 要先用sort排序 O&#xff08;n&#xff09;被O&#xff08;nlogn&#xff09;覆盖

服务器数据恢复—xfs文件系统节点、目录项丢失的数据恢复案例

服务器数据恢复环境&#xff1a; EMC某型号存储&#xff0c;该存储内有一组由12块磁盘组建的raid5阵列&#xff0c;划分了两个lun。 服务器故障&#xff1a; 管理员为服务器重装操作系统后&#xff0c;发现服务器的磁盘分区发生改变&#xff0c;原来的sdc3分区丢失。由于该分区…

葡萄书--深度学习基础

卷积神经网络 卷积神经网络具有的特性&#xff1a; 平移不变性&#xff08;translation invariance&#xff09;&#xff1a;不管检测对象出现在图像中的哪个位置&#xff0c;神经网络的前面几层应该对相同的图像区域具有相似的反应&#xff0c;即为“平移不变性”。图像的平移…

web自动化系列-selenium 的鼠标操作(十)

对于鼠标操作 &#xff0c;我们可以通过click()方法进行点击操作 &#xff0c;但是有些特殊场景下的操作 &#xff0c;click()是无法完成的 &#xff0c;比如 &#xff1a;我想进行鼠标悬停 、想进行鼠标拖拽 &#xff0c;怎么办 &#xff1f; 这个时候你用click()是无法完成的…

渲染技术如何改变影视制作的面貌

随着科技的飞速发展&#xff0c;影视制作领域也迎来了翻天覆地的变化。其中&#xff0c;渲染技术的不断革新&#xff0c;更是对影视制作产生了深远的影响。渲染作为影视制作中的关键环节&#xff0c;渲染技术的提升&#xff0c;不仅提升了画面的质量&#xff0c;还为创作者提供…

计算机网络 Cisco远程Telnet访问交换机和Console终端连接交换机

一、实验要求和内容 1、配置交换机进入特权模式密文密码为“abcd两位班内学号”&#xff0c;远程登陆密码为“123456” 2、验证PC0通过远程登陆到交换机上&#xff0c;看是否可以进去特权模式 二、实验步骤 1、将一台还没配置的新交换机&#xff0c;利用console线连接设备的…

Github 2024-04-17 C开源项目日报Top10

根据Github Trendings的统计,今日(2024-04-17统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量C项目10C++项目2Whisper.cpp: 高性能自动语音识别模型的C/C++移植 创建周期:569 天开发语言:C, C++协议类型:MIT LicenseStar数量:30141 个…

OpenCV基本图像处理操作(六)——直方图与模版匹配

直方图 cv2.calcHist(images,channels,mask,histSize,ranges) images: 原图像图像格式为 uint8 或 float32。当传入函数时应 用中括号 [] 括来例如[img]channels: 同样用中括号括来它会告函数我们统幅图 像的直方图。如果入图像是灰度图它的值就是 [0]如果是彩色图像 的传入的…

在Visual Studio配置C++的netCDF库的方法

本文介绍在Windows电脑的Visual Studio软件中&#xff0c;配置C 语言最新版netCDF库的方法。 netCDF&#xff08;Network Common Data Form&#xff09;是一种用于存储、访问和共享科学数据的文件格式和库&#xff0c;其提供了一种灵活的方式来组织、描述和存储多维数据&#…