【重温设计模式】观察者模式及其Java示例

观察者模式的概念和原理

在编程世界中,设计模式作为一种解决问题的策略,它的存在就如同人类语言中的成语,是一种经过时间考验的有效解决方案。

观察者模式就是其中一种重要的设计模式,它在很多场景中都有着广泛的应用。那么,什么是观察者模式呢?观察者模式,又被称为发布-订阅模式,其基本概念是定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。

它的设计原理就像是一场戏,主角(主题)在舞台上表演,观众(观察者)在台下观看。当主角的表演发生变化时,观众能立即感知到这种变化。在编程领域,观察者模式的应用场景十分广泛,比如GUI中的事件处理,社交网络中的消息推送,甚至是股票交易系统中的价格更新等等。

class OneMoreSubject {private List<Observer> observers = new ArrayList<>();public void addObserver(Observer observer) {observers.add(observer);}public void notifyAllObservers() {for (Observer observer : observers) {observer.update();}}
}

以上是一个简单的观察者模式的Java代码示例,OneMoreSubject类就是我们的主题,它维护了一个观察者列表。当有新的观察者加入时,我们通过addObserver方法将其加入到观察者列表中。当主题的状态发生变化时,我们通过notifyAllObservers方法通知所有的观察者。这样,我们就实现了观察者模式的基本框架。接下来,我们将详细解释观察者模式的主要组成部分,包括主题(Subject)和观察者(Observer),并解释它们的角色和互动方式。

观察者模式的组成部分

在探讨观察者模式的具体应用之前,我们首先需要理解它的主要组成部分。观察者模式主要由两个角色构成,它们分别是主题(Subject)和观察者(Observer)。主题可以被视为数据的提供者,它持有一些重要的状态信息。当这些状态发生变化时,主题会通知所有的观察者。观察者则是数据的接收者,它们订阅了主题,并在主题状态变化时接收通知。主题与观察者之间的关系,就像是一份报纸与它的订阅者,或者是一个B站UP主与它的关注者。

public interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}public interface Observer {void update(OneMore oneMore);
}

在这个简单的Java代码示例中,Subject接口声明了注册(register)、移除(remove)和通知(notify)观察者的方法,而Observer接口则声明了一个更新(update)方法,用于接收主题的状态变化通知。这就是观察者模式的基本构成,通过这种方式,我们可以将数据的提供者和接收者解耦,使得在数据状态变化时,可以灵活地通知到所有关注此变化的观察者。

有了对观察者模式组成部分的理解,我们就可以进一步探讨如何在实际项目中应用观察者模式了。在下一部分,我们将通过一个电子商务系统的Java实例,展示观察者模式的工作流程。

观察者模式的Java实例

在我们刚刚探讨过的观察者模式的主要组成部分——主题(Subject)和观察者(Observer)之后,现在让我们通过一个具体的Java实例来看看观察者模式是如何在实际项目中发挥作用的。假设我们正在开发一个电子商务系统,当一个商品的库存数量发生变化时,需要通知相关的销售人员和采购人员,这就是一个典型的观察者模式的应用场景。

首先,我们定义一个Subject类,这个类有一个OneMore的商品库存数量,当这个数量发生变化时,就需要通知所有的观察者。

public class Subject {private int OneMore;private List<Observer> observers = new ArrayList<>();public void setOneMore(int OneMore) {this.OneMore = OneMore;notifyAllObservers();}public void attach(Observer observer){observers.add(observer);      }public void notifyAllObservers(){for (Observer observer : observers) {observer.update();}} 
}

然后,我们定义一个Observer接口和两个实现这个接口的类:SalesObserverPurchaseObserver,分别代表销售人员和采购人员。

public interface Observer {void update();
}public class SalesObserver implements Observer {public void update() {System.out.println("SalesObserver: OneMore's stock has changed.");}
}public class PurchaseObserver implements Observer {public void update() {System.out.println("PurchaseObserver: OneMore's stock has changed.");}
}

OneMore的库存数量发生变化时,Subject类就会调用notifyAllObservers方法,通知所有的观察者。这样,无论是销售人员还是采购人员,都能够得到库存变化的通知,从而做出相应的行动。这就是观察者模式的工作流程。

implements
implements
contains
1
*
Subject
-int OneMore
-List<Observer> observers
+setOneMore(int OneMore)
+attach(Observer observer)
+notifyAllObservers()
«interface»
Observer
+update()
SalesObserver
+update()
PurchaseObserver
+update()

然而,任何设计模式都有其适用的场景,也有其优缺点。接下来,我们将探讨观察者模式的优缺点,以及在何种情况下应该使用观察者模式。

观察者模式的优缺点

在我们深入探讨观察者模式的优缺点之前,让我们先来描绘一下这种模式的特色。观察者模式是一种行为设计模式,它允许对象在状态发生变化时通知其依赖对象,而无需它们之间直接耦合。这种模式的主要优点是它支持单向依赖,这意味着主题并不关心观察者的具体实现,只关心观察者是否遵循了预定义的接口。这种设计大大提高了代码的灵活性和可重用性。

然而,这种模式也有其缺点。首先,观察者模式可能导致过度通信。当主题的状态发生改变时,所有的观察者都会被通知,即使他们对该变化没有任何兴趣。其次,如果观察者和主题之间存在循环依赖,可能会导致系统陷入无限循环。最后,如果观察者的处理时间过长,可能会阻塞主题的进程。

对于何时使用观察者模式,一般的建议是当你希望在对象的状态改变时,能够通知其他对象,但又不希望这些对象之间存在直接依赖关系时,可以考虑使用观察者模式。例如,一个邮件订阅系统就可以使用观察者模式,当新的邮件到达时,所有订阅者都会收到通知。

总结

总的来说,观察者模式是一种强大的设计模式,它能够帮助我们在系统中实现松耦合的对象间通信。通过这种模式,我们可以使得一个对象的状态变化能够通知到其他的对象,而不需要这些对象之间存在直接的联系。这样,我们就可以实现对象间的动态交互,使得系统更加灵活和可扩展。

但是,我们也需要注意,观察者模式并不是万能的。在某些情况下,它可能会导致过度通信,或者造成系统的循环依赖。因此,我们在使用观察者模式时,需要仔细考虑其适用性,确保它能够帮助我们解决问题,而不是引入新的问题。

我们可能会遇到许多需要使用观察者模式的场景。比如,我们可能需要实现一个社交网络的消息推送系统,或者一个电子商务网站的库存管理系统。在这些场景中,观察者模式都能够发挥其强大的作用。

然而,设计模式只是工具,而不是目标。我们的最终目标,是通过使用这些工具,来编写出高效、可维护、可扩展的代码。因此,我们应该根据实际的需求和场景,灵活地选择和使用设计模式,而不是死板地套用。

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

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

相关文章

外包干了5天,技术退步明显。。。。

说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&a…

Java项目:63 ssm网上花店设计+vue

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 系统具备友好性且功能完善。管理员登录进入后台之后&#xff0c;主要完成花材选择管理&#xff0c;用户管理&#xff0c;鲜花管理&#xff0c;鲜花出入…

【数据结构与算法】(16):桶除了能装饭还能排序?

&#x1f921;博客主页&#xff1a;Code_文晓 &#x1f970;本文专栏&#xff1a;数据结构与算法 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多数据结构与算法点击专栏链接查看&…

源神,启动!马斯克开源史上最大模型Grok,参数高达3140亿,可商用!

马斯克真不愧是源神&#xff0c;自开源X的推荐算法以及特斯拉智能驾驶算法后&#xff0c;又说到做到&#xff0c;开源旗下大模型Grok&#xff01; 代码和模型权重已上线GitHub。官方信息显示&#xff0c;此次开源的Grok-1是一个3140亿参数的混合专家模型&#xff0c;远超OpenAI…

HTML选择文件的实时预览

HTML选择文件的实时预览 目录 HTML选择文件的实时预览HTML代码JS代码预览 HTML代码 <input type"file" id"adv_img_input" style"width: 1000px ;height:30px"> <img src"#"id"adv_img">JS代码 <script>…

配置OGG 如何批量修改源端及目标端序列值_满足客户变态需求学会这招你就赚了

欢迎您关注我的公众号【尚雷的驿站】 **************************************************************************** 公众号&#xff1a;尚雷的驿站 CSDN &#xff1a;https://blog.csdn.net/shlei5580 墨天轮&#xff1a;https://www.modb.pro/u/2436 PGFans&#xff1a;ht…

WanAndroid(鸿蒙版)开发的第三篇

前言 DevEco Studio版本&#xff1a;4.0.0.600 WanAndroid的API链接&#xff1a;玩Android 开放API-玩Android - wanandroid.com 其他篇文章参考&#xff1a; 1、WanAndroid(鸿蒙版)开发的第一篇 2、WanAndroid(鸿蒙版)开发的第二篇 3、WanAndroid(鸿蒙版)开发的第三篇 …

2024年3月GESP认证Scratch图形化编程四级真题及答案

GESP 图形化四级试卷 &#xff08;满分&#xff1a;100 分 考试时间&#xff1a;120 分钟&#xff09; 学校&#xff1a; 姓名&#xff1a; ​ 一、单选题&#xff08;共 10 题&#xff0c;每题 2 分&#xff0c;共 30 分&#xff09; 题号 1 2 3 4 5 6 7 8 9 10 11 1…

【开源】SpringBoot框架开发学生综合素质评价系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学生功能2.2 教师功能2.3 教务处功能 三、系统展示四、核心代码4.1 查询我的学科竞赛4.2 保存单个问卷4.3 根据类型查询学生问卷4.4 填写语数外评价4.5 填写品德自评问卷分 五、免责说明 一、摘要 1.1 项目介绍 基于J…

数字化转型导师坚鹏:人工智能在金融机构数字化转型中的应用

人工智能在金融机构数字化转型中的应用 课程背景&#xff1a; 金融机构数字化转型离不开人工智能&#xff0c;在金融机构数字化转型中&#xff0c;人工智能起到至关重要的作用&#xff0c;很多机构存在以下问题&#xff1a; 不清楚人工智能产业对我们有什么影响&#xff1f;…

考研数学|概率应该怎么学?

考研概率论老师很多&#xff0c;但是我最推荐两个老师&#xff0c;李良和方浩 我认为李良概率论基础讲解相比于其他老师最大的优点就是&#xff0c;每一步都会耐心解释其中的逻辑。很少会像方浩老师那样过于跳跃或者频繁串联&#xff0c;这点对于零基础思维转换慢的人来说&…

Transformer self-attention源码及原理理解

自注意力计算公式&#xff1a; 在公式(1)中Q(query)是输入一个序列中的一个token&#xff0c;K(key)代表序列中所有token的特征。 可以得到当前token与序列中其他token的相关性。在论文原文中512&#xff0c;表示每个token用512维特征表示&#xff08;序列符号的embedding长度…

C语言中大小写字母如何转化

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

Linux TCP参数——tcp_adv_win_scale

文章目录 tcp_adv_win_scaleip-sysctl.txt解释buffering overhead内核缓存和应用缓存示例计算深入理解从2到1(tcp_adv_win_scale的值)总结 tcp_adv_win_scale adv-advise&#xff1b;win-window; 用于指示TCP中接收缓存比例的值。 static inline int tcp_win_from_space(int …

SpringSecurity(SpringBoot2.X版本实现)

资料来源于 SpringSecurity框架教程-Spring SecurityJWT实现项目级前端分离认证授权 侵权删 目录 介绍 快速开始 认证 认证流程 登录校验流程 SpringSecurity完整流程 认证流程详解 代码实现 准备工作 mysql mybatis-plus redis 统一返回类 核心代码 密码加密存…

Mesh网格obj文件构成解析

众所周知&#xff0c;Mesh网格是三维重建的常用手法&#xff0c;通过顶点-三角面的形式来完成对三维物体的表达。其中&#xff0c;最常见的Mesh网格文件格式就是obj格式。看起来复杂的三维形状其实在数值表示上是很简单的&#xff0c;大家跟我一起来做个小实验就好&#xff1a;…

echarts散点图自定义tooltip,鼠标放上去展示多行数据

先放效果图 如图&#xff0c;就是鼠标悬停在散点上&#xff08;这里的散点我替换成了图片&#xff0c;具体做法参考这篇文章&#xff1a;echarts散点图的散点用自定义图片替代-CSDN博客&#xff09;时&#xff0c;可以展示多行数据。之前查找资料的时候&#xff0c;很多用字符串…

练习unittest+Fixture实现

练习01 创建⼀个⽬录 case, 作⽤就是⽤来存放⽤例脚本,在这个⽬录中创建 5 个⽤例代码⽂件 , test_case1.py使⽤ TestLoader 去执⾏⽤例 将来的代码 ⽤例都是单独的⽬录中存放的 test_项⽬_模块_功能.py test_case1.py # 1. 导包 unittest import unittest # 2. 定义测试类, 只…

面试经典150题(114-118)

leetcode 150道题 计划花两个月时候刷完之未完成后转&#xff0c;今天完成了5道(114-118)150 gap 了一周&#xff0c;以后就不记录时间了。。 114.(70. 爬楼梯) 题目描述&#xff1a; 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不…

旅行社旅游线路预定管理系统asp.net

旅行社旅游线路预定管理系统 首页 国内游 境外游 旅游景点 新闻资讯 酒店信息―留言板 后台管理 后台管理导航菜单系统管理修改密码留言管理注册会员管理基础数据设置国别设置有份设地区设置 旅行社管理友情链接管理添加友情链接友情链接管理新闻资讯管理添加新闻资讯新闻资讯管…