设计模式之观察者模式

 

什么是观察者模式

观察者模式是一种对象行为模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在观察者模式中,主题是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。

观察者模式的核心角色

  • 主题(Subject):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。主题提供了添加、删除和通知观察者的方法。
  • 观察者(Observer):观察者是接收主题通知的对象。观察者需要实现一个更新方法,当收到主题的通知时,调用该方法进行更新操作。
  • 具体主题(Concrete Subject):具体主题是主题的具体实现类。它维护着观察者列表,并在状态发生改变时通知观察者。
  • 具体观察者(Concrete Observer):具体观察者是观察者的具体实现类。它实现了更新方法,定义了在收到主题通知时需要执行的具体操作。

观察者模式如何实现

需求描述

明朝的锦衣服制度是一种特殊的政治制度,锦衣卫表面是上负责帮助皇帝管理仪仗,实际上是直属皇帝的特务机构,皇帝感觉哪个大臣有安全隐患,都会指挥锦衣卫派上一个眼线进行潜伏,暗中观察其一举一动,一旦有什么不好苗头,潜伏的眼线都会立马向上报告,锦衣卫马上出动进行逮捕、审讯。这一套流程下来,实际上就是观察者模式。如果写一个程序,怎么实现这个过程呢?

实现方法

1、定义一个抽象的观察者,也就是锦衣卫,用来定义具体的职能,如逮捕、审讯等;

/** *锦衣卫 */ public interface JinYiWei { /** * 逮捕 */ void arrest(String something); }

2、定义一个抽象主题,也就是眼线,用来执行添加观察者、删除观察者、通知观察者;

/** * 眼线 */ public abstract class YanXian { public List<JinYiWei> jinYiWeiList = new ArrayList<JinYiWei>(); /** * 添加 * * @param jinYiWei */ public void add(JinYiWei jinYiWei) { this.jinYiWeiList.add(jinYiWei); } /** * 移除 * * @param jinYiWei */ public void remove(JinYiWei jinYiWei) { this.jinYiWeiList.remove(jinYiWei); } public abstract void report(String something); }

3、定义具体的主题,也就是皇帝的大臣,继承于抽象的主题,也就是眼线,大臣不管做什么事,都在被眼线的暗中观察着,并报告上级。

/** * 尚书大人 */ public class ShangShu extends YanXian { private String name; public ShangShu(String name) { this.name = name; } public void doSomething(String something) { System.out.println(this.name + something); //观察者开始工作 this.report(this.name + something); } @Override public void report(String something) { for (JinYiWei jinYiWei : this.jinYiWeiList) { jinYiWei.arrest(something); } } }

4、定义具体的观察者,也就锦衣卫的XX千户、XX 指挥使,用来执行具体的职能任务,如逮捕、审讯等;

/** * 锦衣卫千户大人 */ public class QianHu implements JinYiWei { private String name; public QianHu(String name) { this.name = name; } @Override public void arrest(String something) { System.out.println("报告皇帝:" + something); System.out.println(this.name + "准备执行逮捕任务"); } }

5、客户端

public class Client { public static void main(String[] args) { JinYiWei jinYiWei=new QianHu("锦衣卫的马千户"); ShangShu shangShu = new ShangShu("吏部的李尚书"); shangShu.add(jinYiWei); shangShu.doSomething("写了一首反诗"); ShangShu shangshu2=new ShangShu("兵部的王尚书"); shangshu2.add(jinYiWei); shangshu2.doSomething("买了十副盔甲"); } }

如何扩展

最近朱皇帝收到风声,将军们开始骄奢淫逸了,甚至开始强抢民女了,于派安插眼线,暗中搜集罪证,一旦证据确凿,马上逮捕,怎么实现这个过程呢?

定义具体的主题,也就是皇帝的将军,继承于抽象的主题,也就是眼线,将军们不管做什么事,都在被眼线的暗中观察着,并报告上级。

/** * 将军 */ public class JiangJun extends YanXian{ private String name; public JiangJun(String name) { this.name = name; } public void doSomething(String something){ System.out.println(this.name+something); this.report(this.name+something); } @Override public void report(String something) { for (JinYiWei jinYiWei : jinYiWeiList) { jinYiWei.arrest(something); } } }

public class Client { public static void main(String[] args) { JinYiWei jinYiWei=new QianHu("锦衣卫的马千户"); ShangShu shangShu = new ShangShu("吏部的李尚书"); JiangJun jiangJun = new JiangJun("李将军"); jiangJun.add(jinYiWei); jiangJun.doSomething("纵容部下强抢民女"); } }

观察者模式适用哪些场景

业务场景具有下面的特征就可以使用观察者模式:

  1. 当一个抽象模型有两个方面,其中一个方面依赖于另一方面
  2. 当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变

有没有比较具体的业务场景示例呢?当然有,比如:

  1. 新闻评论功能:在此功能中,用户可以发布或删除留言,并自动追加留言和更新留言条数。为了实现这一功能,可以使用观察者模式。具体来说,留言模块、用户模块和提交模块可以作为被观察对象,而观察者模式可以用于在被观察对象发布消息时自动通知和更新观察者对象(例如,追加留言或更新留言条数)。
  2. 事件驱动的系统:观察者模式也适用于事件驱动的系统。在这种系统中,当一个事件发生时,需要通知所有注册过的观察者。观察者模式可以提供一种方便的方式来管理和通知所有的观察者。
  3. 数据变更通知:在某些业务场景中,当数据发生变更时,需要通知相关的用户或系统。观察者模式可以用于在这种数据变更发生时自动通知所有的观察者。
  4. 消息推送系统:在消息推送系统中,当有新的消息产生时,需要推送给相关的用户。观察者模式可以用于在这种消息发布时自动通知和更新观察者对象。
  5. 库存管理系统:在库存管理系统中,当库存量发生变化时,需要通知所有关注此变化的用户或系统。比如,当库存量低于某个阈值时,需要自动发送通知给负责补货的部门或人员。

观察者模式在Spring中的应用

  1. Spring MVC中的控制器(Controller):Spring MVC中的控制器类似于观察者模式中的观察者,它们监听并响应应用程序状态的变化。当应用程序状态发生变化时,控制器会接收到通知并执行相应的操作。
  2. Spring消息代理(Message Proxy):Spring消息代理可以用于实现异步消息通知。通过代理模式和观察者模式的结合使用,可以在应用程序中实现消息的自动分发和订阅。
  3. Spring AOP(面向切面编程):Spring AOP可以用于实现切面通知。通过使用观察者模式,可以在程序运行时自动执行切面逻辑,例如日志记录、事务管理等。
  4. Spring事件系统(Event System):Spring事件系统可以用于实现事件的发布和订阅。通过观察者模式,可以将事件和观察者关联起来,当事件发生时,所有订阅了该事件的观察者都会接收到通知。
  5. Spring消息队列(Message Queue):Spring消息队列可以用于实现消息的异步处理和消息的分布式发送。通过观察者模式,可以将消息队列和观察者关联起来,当有新消息到达时,所有订阅了该队列的观察者都会接收到通知。

关于观察者模式与监听器模式

从某种角度来说,观察者模式与监听器模式可以理解是一会事,但是从具体的实现细节上来说,还是有一些区别:

  • 观察者模式定义了一种一对多的依赖关系,使得当一个主题对象的状态发生变化时,所有依赖它的观察者都会得到通知并自动更新。在这种模式中,主题对象维护了一个观察者列表,并在其状态发生变化时通知所有的观察者。观察者对象不知道其他观察者的存在,它只知道如何更新自己。这种模式更适合于一对多的场景。
  • 监听器模式则是一种更适合一对一的通信场景的模式。在监听器模式中,监听器对象注册到时间源对象上,当时间源对象发生变化时,它会通知所有注册过的监听器。监听器对象知道其他监听器的存在,并且可以相互交互。在Springboot中,已经实现了具体的监听器机制,之前输出过两篇文章:
    • Springboot事件监听机制:实战应用_spring事件监听应用场景
    • Springboot事件监听机制:工作原理

总结

优点

  1. 观察者模式在被观察者和观察者之间建立一个抽象的耦合,使得它们可以属于不同的抽象化层次。
  2. 观察者模式支持广播通信,即当被观察者的状态发生变化时,会通知所有的观察者。
  3. 观察者模式的实现方式符合“开闭原则”,即可以在不改变已存在的实现类的情况下,增加新的观察者类。

缺点

  1. 如果被观察者对象有很多的直接和间接的观察者,那么将所有的观察者都通知到会花费很多时间。
  2. 如果在被观察者和观察者之间存在循环依赖,那么它们之间会触发循环调用,可能导致系统崩溃。
  3. 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

总之,观察者模式是一种非常有效的行为型设计模式,但是在使用观察者模式时需要谨慎考虑其优缺点,并确保在实践中能够有效地应用这种设计模式。

 

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

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

相关文章

人工智能基础_机器学习017_SGD随机梯度下降求解多元一次方程_以及求解多元一次方程---人工智能工作笔记0057

然后我们再来看一下X.shape 这个用来显示,一个矩阵的形状,其实就是几行几列对吧 然后,比如上面这个是100行 ,9列,其实对应我们的方程上,就是 8元一次方程, w1到w8加上w0 一共9列,然后有100个样本,也就是100行数据对吧 然后我们来看一下我们用SGD随机梯度下降来实现一个一元一…

java--构造器

1.构造器是什么样子 构造器分为无参构造(就相当于你有车子&#xff0c;但是里面是空的)和带参构造(就相当于你有车子&#xff0c;里面还有几个妹纸&#xff0c;你真该死啊) 2.构造器有什么特点 创建对象时&#xff0c;对象会去调用构造器。 3.构造器的常见应用场景 创建对象…

人工智能基础_机器学习006_有监督机器学习_正规方程的公式推导_最小二乘法_凸函数的判定---人工智能工作笔记0046

我们来看一下公式的推导这部分比较难一些, 首先要记住公式,这个公式,不用自己理解,知道怎么用就行, 比如这个(mA)T 这个转置的关系要知道 然后我们看这个符号就是求X的导数,X导数的转置除以X的导数,就得到单位矩阵, 可以看到下面也是,各种X的导数,然后计算,得到对应的矩阵结…

云原生安全日志审计

记得添加&#xff0c;把配置文件挂载进去 - mountPath: /etc/kubernetes/auditname: audit-policyreadOnly: true.....- hostPath:path: /etc/kubernetes/audit/type: DirectoryOrCreatename: audit-policy/etc/kubernetes/manifests/kube-apiserver.yaml 具体配置文件如下 a…

RHCE第二次作业

配置ssh远程连接 1.实现两台linux主机之间通过公钥验证能够互相实现免密登陆 1.1交互式 1&#xff09;客户端&#xff08;client&#xff09;生成非对称秘钥 [rootserver2 ~]# ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the ke…

蓝鹏测控测宽仪系列又添一员大将——双目测宽仪

轧钢过程中钢板的宽度是一个重要的参数&#xff0c;它直接决定了成材率。同时&#xff0c;随着高新科技越来越广泛的应用到工程实际中&#xff0c;许多控制系统需要钢板实时宽度值作为模型参数。 当前&#xff0c;相当一部分宽厚板厂还在采用人工检测的方法&#xff0c;检测环境…

LiveMeida视频接入网关

一、产品简介 视频接入网关主要部署在视频存储节点或视频汇聚节点&#xff0c;面向不同用户&#xff0c;主要用于对接不同厂家、不同型号的摄像机设备&#xff0c;获取摄像机视频后&#xff0c;以统一标准的视频格式和传输协议&#xff0c;将视频推送至上层联网/应用平台。可广…

WoShop跨境电商源码:解放你的双手,批量发货轻松搞定

随着跨境电商的快速发展&#xff0c;越来越多的企业开始涉足这一领域。在这个过程中&#xff0c;如何高效地处理批量发货成为了亟待解决的问题。本文将探讨跨境电商源码支持批量发货的优势、需求分析、实现方案、技术实现、测试与维护以及总结与建议。 一、引言 在跨境电商领域…

uniapp 查看安卓第三方插件抛出的异常

0.安装好andriod studio 和hbuilder 1.配置环境变量 鼠标右键此电脑-》设置》关于》高级系统设置》环境变量》系统变量》path中加入 具体的hbuildr adb目录看个人 2.在cmd中输入命令adb version 查看是否配置成功 出现版本号就是配置成功了 3.去hbuilder中&#xff0c;导航栏…

京东科技埋点数据治理和平台建设实践 | 京东云技术团队

导读 本文核心内容聚焦为什么要埋点治理、埋点治理的方法论和实践、奇点一站式埋点管理平台的建设和创新功能。读者可以从全局角度深入了解埋点、埋点治理的整体思路和实践方法&#xff0c;落地的埋点工具和创新功能都有较高的实用参考价值。遵循埋点治理的方法论&#xff0c;…

【Linux】安装使用Nginx负载均衡,并且部署前端项目

目录 一、Nginx概述 1. 什么 2. 背景 3. 作用 二、Nginx负载均衡 1. 讲述 2. 使用 1. 下载 2. 安装 3. 负载均衡 三、前端部署 1. 准备 2. 部署 一、Nginx概述 1. 什么 Nginx是一个高性能的开源Web服务器和反向代理服务器。它具有轻量级、高并发、低内存消耗的…

宽带电力载波稳定吗?有丢数据吗?

随着我国智能电网建设的推进&#xff0c;宽带电力载波技术作为一种集电力传输与信息通信于一体的技术&#xff0c;得到了广泛关注。然而&#xff0c;宽带电力载波通信在实际应用过程中&#xff0c;稳定性问题及数据丢失现象成为制约其发展的瓶颈。为了进一步提高宽带电力载波的…