行为设计模式 -观察者模式- JAVA

观察者模式

    • 一.简介
    • 二. 案例
      • 2.1 抽象主题(Subject)
      • 2.2 具体主题(Concrete Subject)
      • 2.3 抽象观察者(Observer)
      • 2.4 具体观察者(Concrete Observer)
      • 2.5 测试
    • 三. 结论
      • 3.1 优缺点
      • 3.2 使用场景

前言

这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。

作者:神的孩子都在歌唱

一.简介

百度百科: 观察者模式是一种对象行为模式。又被称为发布-订阅(Publish/Subscribe)模式, 它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在观察者模式中,主体是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。观察者模式不仅被广泛应用于软件界面元素之间的交互,在业务对象之间的交互、权限管理等方面也有广泛的应用。

个人理解: 这个模式在日常开发中很常见,比如a服务想要b服务磁盘满的时候通知它,那么它只需要把自己的grpc或者http接口给到b服务,b服务订阅后,如果磁盘满了就调用a服务注册的接口 通知。

在观察者模式中有如下角色:

  • 抽象主题(Subject) 它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
  • 具体主题(Concrete Subject): 将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
  • 抽象观察者(Observer): 为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
  • 具体观察者(Concrete Observer): 实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。

二. 案例

我将实现一个简单的主题(Subject)观察者(Observer)可以注册到该主题。每当有新消息发布到主题时,所有注册观察者都会收到通知,并且他们可以使用该消息。

请添加图片描述

这里是基本Subject接口,它定义了任何具体主题要实现的接口方法。

2.1 抽象主题(Subject)

/*** @author chenyunzhi* @date 2024/6/5 17:13* @Description 主题*/
public interface Subject {/*** 注册观察者*/void register(Observer observer);/*** 取消观察者*/void unregister(Observer observer);/*** 通知观察者消息有更新*/void notifyObservers();}

2.2 具体主题(Concrete Subject)

/*** @author chenyunzhi* @date 2024/6/5 17:21* @Description 实现主题*/
public class SubjectImpl implements Subject{/*** 同步锁*/private final Object SUB= new Object();/*** 存储注册的观察者*/private final List<Observer> observers = new ArrayList<>();/*** 要通知的消息*/private String message;/*** 防止 notifyObservers方法被外部调用发送错误通知*/private boolean flag;@Overridepublic void register(Observer observer) {if (observer != null) {synchronized (SUB) {// 如果不在就存储if (!observers.contains(observer)) {observers.add(observer);}}}}@Overridepublic void unregister(Observer observer) {if (observer != null) {synchronized (SUB) {observers.remove(observer);}}}@Overridepublic void notifyObservers() {List<Observer> objects = new ArrayList<>();//使用同步方法确保通知仅发送给新消息前注册的观察者synchronized (SUB) {if (!flag) {return;}objects = this.observers;this.flag = false;}for (Observer observer:objects) {// 通知观察者,有消息更新observer.update(this.message);}}/*** 自定义一个消息变更方法方便测试*/public void updateMessage(String message) {System.out.println("消息有变更,通知注册的观察者");this.message = message;this.flag = true;// 通知notifyObservers();}
}

2.3 抽象观察者(Observer)

/*** @author chenyunzhi* @date 2024/6/5 17:14* @Description 观察者类*/
public interface Observer {/*** 定义要更新的方法,由主题调用*/void update(String msg);
}

2.4 具体观察者(Concrete Observer)

/*** @author chenyunzhi* @date 2024/6/5 17:59* @Description 观察者实现类*/
public class ObserverImpl implements Observer{/*** 观察者名称*/private final String observerName;public ObserverImpl(String name) {this.observerName = name;}@Overridepublic void update(String msg) {System.out.println(observerName + "接收到消息:" + msg);}
}

2.5 测试

/*** @author chenyunzhi* @date 2024/6/6 14:57* @Description 观察者模式测试*/
public class ObserverPatternTest {public static void main(String[] args) {// 创建观察者并注册到主题SubjectImpl subject = new SubjectImpl();subject.register(new ObserverImpl("观察者1"));subject.register(new ObserverImpl("观察者2"));subject.register(new ObserverImpl("观察者3"));// 测试 更新消息subject.updateMessage("订阅的主题有消息更新了");}
}

请添加图片描述

三. 结论

3.1 优缺点

1.优点:

  • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
  • 被观察者发送通知,所有注册的观察者都会收到信息【可以实现广播机制】

2.缺点:

  • 如果观察者非常多的话,那么所有的观察者收到被观察者发送的通知会耗时
  • 如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调用,会导致系统崩溃

3.2 使用场景

  • 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时。

作者:神的孩子都在歌唱

本人博客:https://blog.csdn.net/weixin_46654114

转载说明:务必注明来源,附带本人博客连接。

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

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

相关文章

STM32外设详解——ADC

来源&#xff1a;铁头山羊 基本概念 ①ADC是模数转换器的统称&#xff0c;stm32f103c8t6内部集成了2个12位主次逼近型ADC&#xff0c;外设名称为ADC1、ADC2。 ② 采样深度为12位意味着ADC可以将0~3.3V的模拟电压等比转换为0~4095的数字值&#xff08;分割为2的12次方份&…

网 络 安 全

网络安全是指保护网络系统及其所存储或传输的数据免遭未经授权访问、使用、揭露、破坏、修改或破坏的实践和技术措施。网络安全涉及多个方面&#xff0c;包括但不限于以下几个方面&#xff1a; 1. 数据保护&#xff1a;确保数据在传输和存储过程中的完整性和保密性&#xff0c;…

银河麒麟V10安装ToDesk远程控制

银河麒麟V10安装ToDesk远程控制 ARM版本安装 1.下载arm的deb包 wget https://dl.todesk.com/linux/todesk_4.0.3_aarch64.deb2.安装 sudo apt-get install ./todesk_4.0.3_aarch64.deb3.启动todesk todesk

文献翻译用什么软件?新手建议收藏这5个

在学术研究的广阔天地里&#xff0c;语言障碍往往是科研人员不得不跨越的一道难关。 面对海量的外文文献&#xff0c;如何高效、准确地获取其中的信息&#xff0c;成为了许多学者关注的焦点。 想知道文献翻译器推荐哪一个&#xff1f;今天这篇文章为大家推荐5个优秀的文献翻译…

如何制作低代码开发的视频教程?

如何制作低代码开发的视频教程&#xff1f; 随着数字化转型的加速&#xff0c;越来越多的企业和组织开始采用低代码开发平台来加速应用程序的构建。对于许多开发者和业务人员来说&#xff0c;学习如何使用这些平台可以显著提高工作效率。因此&#xff0c;创建一份清晰、实用且…

02_InFluxDb

InFluxDb 初始化初始化流程 交互InFluxDbWebUI交互 数据模型行协议添加标签数据格式 数据类型空格索引 Flux语言 初始化 初始化流程 用户 密码 组织名称 Bucket—mysql里面的数据库概念 交互InFluxDb 暂用了8086端口.提供了 http api WebUI交互 略... 数据模型 这是mys…

无源有损耗导电介质的平面电磁波——复数介电常数带来复波数k(导致幅度衰减)和复波阻抗(带来磁场电场相位不同)

推导中以εμσ是实数为假设 注意在线性介质中J 0和σ等于0其实是一个条件&#xff0c;因为J σE 线性介质的麦克斯韦方程 线性介质无源无损耗条件下 线性介质无源有损耗导电介质下 无源有损耗的复数麦克斯韦方程组&#xff0c;只有方程二与无源无损耗的麦克斯韦方程组不同…

双十一选购攻略:2024年双十一有什么值得入手好物?

又到一年双11&#xff0c;还有很多持币观望的小伙伴&#xff0c;可能还没想要买什么&#xff0c;所以我就来啦&#xff0c;给大家参谋参谋&#xff0c;结合我生活中的好物使用经验&#xff0c;来跟大家做个分享&#xff0c;如果能给已经进入双11“买买买”节奏的你一些参考&…

java.lang.NoClassDefFoundError: kotlin/Result解决方案

问题 在控制窗口上虽然报错是找不到对应的class&#xff0c;但是呢在我们导入kotlin的后&#xff0c;还是报相同的异常&#xff0c;在网上查找了各种资料&#xff0c;都没有解决方案。 问题分析 在idea2021之后&#xff0c;kotlin都使用远程仓库&#xff08;kotlinx-coeouti…

C语言 动态数据结构的C语言实现内存映像

C程序的内存映像 C程序中变量的内存分配方式  C程序中变量的内存分配方式  从静态存储区分配  全局变量和静态变量 C程序中变量的内存分配方式  从静态存储区分配  全局变量和静态变量  在栈上分配  存放函数参数值&#xff0c;局部变量值等  …

1.1 flexsim基础入门

连线和端口 A&#xff1a;连接 S&#xff1a;中间端口连接 &#xff08;经常用于货物搬运的时候&#xff0c;中间端口连接属于无方向连接&#xff09; 假设有一个任务分配器&#xff0c;用来分配任务。暂存区与任务分配器连接&#xff0c;说明通过任务分配器作为中间商下达任务…

【重学 MySQL】五十、添加数据

【重学 MySQL】五十、添加数据 使用INSERT INTO语句添加数据基本语法示例插入多行数据注意事项 使用LOAD DATA INFILE语句批量添加数据其他插入数据的方式注意事项 在MySQL中&#xff0c;添加数据是数据库操作中的基本操作之一。 使用INSERT INTO语句添加数据 使用 INSERT IN…

GPT系列

GPT&#xff08;Generative Pre-Training&#xff09;&#xff1a; 训练过程分两步&#xff1a;无监督预训练有监督微调 模型结构是decoder-only的12层transformer 1、预训练过程&#xff0c;窗口为k&#xff0c;根据前k-1个token预测第k个token&#xff0c;训练样本包括700…

配置静态ip

背景:因业务需要需要将一台服务器从机房搬到实验室,机房是光纤,实验室是网线,需要重新配置下静态ip 确认网络配置文件(网上没找到,不清楚一下方法对不对) 先随便一个网口连接网线,执行 ifconfig -a 找到带“RUNNING”的(lo不是哈)----eno1 到/etc/sysconfig/network…

ansible 剧本模式

目录 1.剧本格式 ​编辑​编辑2.案例1创建目录分发文件剧本 2.1剧本中用到的命令 2.2书写具体剧本 3.案例2 分发 安装软件包 启动服务的剧本 3.1下载软件包 3.2用yum安装 3.3启动服务 4.找出ansible中对应的模块 5.剧本实现 4.ansible 剧本变量 4.1常用的…

YOLO11涨点优化:注意力魔改 | 轻量级自注意力机制CoordAttention | CVPR2021

💡💡💡本文改进内容:CoordAttention优势,不仅会考虑输入的特征信息,还会考虑每个像素点的位置信息,从而更好地捕捉空间上的局部关系和全局关系。 💡💡💡本文改进:分别加入到YOLO11的backbone、neck、detect,助力涨点 改进1结构图: 改进2结构图: 改进3结构

【HTTPS】深入解析 https

我的主页&#xff1a;2的n次方_ 1. 背景介绍 在使用 http 协议的时候是不安全的&#xff0c;可能会出现运营商劫持等安全问题&#xff0c;运营商通过劫持 http 流量&#xff0c;篡改返回的网页内容&#xff0c;例如广告业务&#xff0c;可能会通过 Referer 字段 来统计是…

【Java】—— 泛型:泛型的理解及其在集合(List,Set)、比较器(Comparator)中的使用

目录 1. 泛型概述 1.1 生活中的例子 1.2 泛型的引入 2. 使用泛型举例 2.1 集合中使用泛型 2.1.1 举例 2.1.2 练习 2.2 比较器中使用泛型 2.2.1 举例 2.2.2 练习 1. 泛型概述 1.1 生活中的例子 举例1&#xff1a;中药店&#xff0c;每个抽屉外面贴着标签 举例2&…

图示详解OpenEuler下 DNS安装、配置与测试

前言 DNS配置内容、步骤、参数较多&#xff0c;初学者很难短时间掌握&#xff0c;另外&#xff0c;理解DNS工作原理也有一定的难度&#xff0c;一次配置成功的概率不大&#xff0c;因此&#xff0c;建议在配置DNS之前&#xff0c;先读一下之前笔者的博文《详解DNS工作原理及实…

(20)MATLAB使用卡方(chi-square)分布生成Nakagami-m分布

文章目录 前言一、使用卡方分布函数生成Nakagami分布随机变量二、MATLAB仿真1.仿真代码2.运行结果 前言 Nakagami分布随机变量的生成&#xff0c;可以使用gamma分布实现&#xff0c;也可以使用卡方&#xff08;chi-square&#xff09;分布随机变量生成。使用伽马&#xff08;g…