当前位置: 首页 > news >正文

【设计模式】详解观察者模式

文章目录

  • 1、简介
  • 2、观察者模式简单实现
    • 抽象主题(Subject)
    • 具体主题(ConcreteSubject)
    • 抽象观察者(Observer)
    • 具体观察者(ConcrereObserver)
    • 测试:
  • 观察者设计模式优缺点
    • 观察者模式的优点包括:
    • 观察者模式的缺点包括:

1、简介

观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新。(MQ和它有点像)
当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。
在这里插入图片描述
观察者模式中,一共有四种角色:

  1. Subject(抽象主题):也称为被观察者或可观察者,它是具有状态的对象,并维护着一个观察者列表。抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者。主题提供了添加、删除和通知观察者的方法。一般用一个抽象类或者一个接口实现
  2. Observer(抽象观察者):为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者角色一般用一个抽象类或者一个接口实现。在这个示意性的实现中,更新接口只包含一个方法(即Update()方法),这个方法叫做更新方法。
  3. ConcreteSubject(具体主题):也可称为具体被观察者,该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
  4. ConcrereObserver(具体观察者):实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。如果需要,具体现察者角色可以保存一个指向具体主题对象的引用。

从具体主题角色指向抽象观察者角色的合成关系,代表具体主题对象可以有任意多个对抽象观察者对象的引用。之所以使用抽象观察者而不是具体观察者,意味着主题对象不需要知道引用了哪些ConcreteObserver类型,而只知道抽象Observer类型。这就使得具体主题对象可以动态地维护一系列的对观察者对象的引用,并在需要通知的时候调用每一个观察者共有的update()更新方法。这种做法叫做"针对抽象编程"。

2、观察者模式简单实现

拿博客专栏订阅为例,网站用户的博客专栏为被观察者,用户为观察者,当有多个用户关注了yhz的JVM专栏,当yhz的JVM专栏更新时就会通知这些订阅的用户。

抽象主题(Subject)

package DesignModel.Observer;import java.util.ArrayList;/*** @BelongsProject: 3.9.demo* @Author: yhz* @CreateTime: 2023-07-26  17:58* @Description: TODO* @Version: 1.0*/
public abstract class Subject {//定义一个订阅者集合用于存储所有订阅了这个专栏的用户对象protected ArrayList<Observer>observers = new ArrayList();//注册方法,用于向订阅者集合中增加一个订阅者public void attach( Observer observer ) {observers.add( observer );}//注销方法,用于在订阅者集合中删除一个订阅者public void detach( Observer observer ) {observers.remove( observer );}//通知所有订阅者更新消息public abstract void notifyObservers(String message);
}

具体主题(ConcreteSubject)

yhz的这个专栏为具体主题,里面存储了订阅该专栏的网站用户,并实现了抽象主题中的通知方法:

package DesignModel.Observer;/*** @BelongsProject: 3.9.demo* @Author: yhz* @CreateTime: 2023-07-26  18:18* @Description: TODO* @Version: 1.0*/
public class ConcreteSubject extends Subject{//重写通知方法为自己的@Overridepublic void notifyObservers(String message) {//通知订阅了该主题的所有订阅者for(Observer observer:observers){observer.update(message);}}
}

抽象观察者(Observer)

package DesignModel.Observer;public interface Observer {//声明了更i性能方法void update(String message);
}

具体观察者(ConcrereObserver)

网站用户作为具体观察者,里面实现了更新的方法

package DesignModel.Observer;/*** @BelongsProject: 3.9.demo* @Author: yhz* @CreateTime: 2023-07-26  18:06* @Description: TODO* @Version: 1.0*/
public class Blooger implements Observer{//博主名称private String bloogerName;public Blooger(String bloogerName) {this.bloogerName = bloogerName;}@Overridepublic void update(String message) {System.out.println(bloogerName+message);}
}

测试:

package DesignModel.Observer;/*** @BelongsProject: 3.9.demo* @Author: yhz* @CreateTime: 2023-07-26  18:21* @Description: TODO* @Version: 1.0*/
public class Test {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();Blooger blooger = new Blooger("aa1");Blooger blooger2 = new Blooger("aa2");Blooger blooger3 = new Blooger("aa3");Blooger blooger4 = new Blooger("aa4");subject.attach(blooger);subject.attach(blooger2);subject.attach(blooger3);subject.attach(blooger4);subject.notifyObservers("您关注的yhz更新了博客");}
}

结果打印:

aa1您关注的yhz更新了博客
aa2您关注的yhz更新了博客
aa3您关注的yhz更新了博客
aa4您关注的yhz更新了博客

观察者设计模式优缺点

观察者模式的优点包括:

  • 降低了主题与观察者之间的耦合关系,两者之间是抽象耦合关系。可以很容易扩展观察者和被观察者。
  • 主题与观察者之间建立了一套触发机制。

观察者模式的缺点包括:

  • 主题与观察者之间的依赖关系并没有完全解除。
  • 当观察者对象很多时,通知的发布会花费很长时间,影响程序效率。
  • 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
  • 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

在使用观察者模式时,需要谨慎处理这些问题,以确保系统的稳定性和效率。

相关文章:

【设计模式】详解观察者模式

文章目录 1、简介2、观察者模式简单实现抽象主题&#xff08;Subject&#xff09;具体主题&#xff08;ConcreteSubject&#xff09;抽象观察者&#xff08;Observer&#xff09;具体观察者&#xff08;ConcrereObserver&#xff09;测试&#xff1a; 观察者设计模式优缺点观察…...

用html+javascript打造公文一键排版系统8:附件及标题排版

最近工作有点忙&#xff0c;所 以没能及时完善公文一键排版系统&#xff0c;现在只好熬夜更新一下。 有时公文有包括附件&#xff0c;招照公文排版规范&#xff1a; 附件应当另面编排&#xff0c;并在版记之前&#xff0c;与公文正文一起装订。“附件”二字及附件顺序号用3号黑…...

微服务体系<1>

我们的微服务架构 我们的微服务架构和单体架构的区别 什么是微服务架构 微服务就是吧我们传统的单体服务分成 订单模块 库存模块 账户模块单体模块 是本地调用 从订单模块 调用到库存模块 再到账户模块 这三个模块都是调用的同一个数据库 这就是我们的单体架构微服务 就是…...

M5ATOMS3基础02传感器MPU6886

M5ATOMS3基础01按键 简洁版本 MPU6886是一款6轴IMU单元&#xff0c;具有3轴重力加速度计和3轴陀螺仪。它采用16位ADC&#xff0c;内置可编程数字滤波器和片上温度传感器&#xff0c;并通过I2C接口&#xff08;地址为0x68&#xff09;与上位机通信。MPU6886支持低功耗模式&#…...

vue 快速自定义分页el-pagination

vue 快速自定义分页el-pagination template <div style"text-align: center"><el-paginationbackground:current-page"pageObj.currentPage":page-size"pageObj.page":page-sizes"pageObj.pageSize"layout"total,prev,…...

0-虚拟机补充知识

虚拟机克隆 如果想要构建服务器集群&#xff0c;没有必要一台一台的去进行安装&#xff0c;只要通过克隆就可以。 快速获得多台服务器主要有两种方式&#xff0c;分别为&#xff1a;直接拷贝操作和vmware的克隆操作 直接拷贝 将之前安装虚拟机的所有文件进行拷贝&#xff0…...

如何将电机控制器添加到您的 ROS 机器人

一、说明 如果您正在构建与 ROS/ROS2 一起使用的移动机器人,您需要做的第一件事就是集成电机控制器。电机控制器的目的是接受来自更高级别的软件(如导航堆栈)的消息,并将其转换为驱动电机的信号。它还将从电机的编码器接收信息,以计算机器人的速度和位置。 您可以…...

ChatGPT统计“一到点就下班”的人数

ChatGPT统计“一到点就下班”的人数 1、到点下班 Chatgpt统计各部门F-D级员工到点下班人数占比&#xff0c;是在批评公司内部存在到点下班现象。 根据图片&#xff0c;该占比的计算方法是&#xff1a;最后一次下班卡在17:30-17:40之间&#xff0c;且1-5月合计有40天以上的人…...

Games101学习笔记 - 变换矩阵基础

二维空间下的变换 缩放矩阵 缩放变换: 假如一个点&#xff08;X,Y&#xff09;。x经过n倍缩放&#xff0c;y经过m倍缩放&#xff0c;得到的新点&#xff08;X1&#xff0c;Y1&#xff09;&#xff1b;那么新点和远点有如下关系&#xff0c;X1 n*X, Y1 m*Y写成矩阵就是如下…...

Ubuntu18.04未安装Qt报qt.qpa.plugin could not load the Qt platform plugin xcb问题的解决方法

在Ubuntu 18.04开发机上安装了Qt 5.14.2&#xff0c;当将其可执行程序拷贝到另一台未安装Qt的Ubuntu 18.04上报错&#xff1a;拷贝可执行程序前&#xff0c;使用ldd将此执行程序依赖的动态库也一起拷贝过去&#xff0c;包括Qt5.14.2/5.14.2/gcc_64/plugins目录系的platforms目录…...

GPT4ALL私有化部署 01 | Python环境

进入以下链接&#xff1a; https://www.python.org/downloads/release/python-3100/ 滑动到底部 选择你系统对应的版本&#xff0c;如果你是win&#xff0c;那么大概率是win-64bit 有可能你会因为网络的问题导致下载不了&#xff0c;我提供了 链接 接着只需要打开 等待…...

GPT-AI 使用的技术概览

ChatGPT 使用的技术概览 智心AI-3.5/4模型&#xff0c;联网对话&#xff0c;MJ快速绘画 从去年 OpenAI 发布 ChatGPT 以来&#xff0c;AI 的能力再次惊艳了世人。在这样的一个时间节点&#xff0c;重新去学习相关技术显得很有必要。 ChatGPT 的内容很多&#xff0c;我计划采用…...

NoSQL-Redis持久化

NoSQL-Redis持久化 一、Redis 高可用&#xff1a;1.概述&#xff1a; 二、Redis持久化&#xff1a;1.持久化的功能&#xff1a;2.Redis 提供两种方式进行持久化&#xff1a; 三、RDB 持久化&#xff1a;1.定义&#xff1a;2.触发条件&#xff1a;3.执行流程&#xff1a;4.启动时…...

关于uniapp中的日历组件uni-calendar中的小红点

关于uniapp中的日历组件uni-calendar中的小红点 如果你使用过uni-calendar组件&#xff0c;可能你觉得这个小红点有点碍眼&#xff0c;但是官方给定的日历组件uni-calendar中如果你想要在某一天上添加一些信息例如:价格&#xff0c;签到&#xff0c;打卡之类&#xff0c;只要标…...

【Nodejs】Node.js简介

1.前言 Node 的重要性已经不言而喻&#xff0c;很多互联网公司都已经有大量的高性能系统运行在 Node 之上。Node 凭借其单线程、异步等举措实现了极高的性能基准。此外&#xff0c;目前最为流行的 Web 开发模式是前后端分离的形式&#xff0c;即前端开发者与后端开发者在自己喜…...

SpringBoot整合Druid

在Spring Boot中整合Druid时&#xff0c;需要导入Druid和JDBC的相关依赖&#xff0c;但不需要额外导入单独的JDBC包。 Druid是一个用于数据库连接池和监控的开源框架&#xff0c;它已经包含了对JDBC的实现。因此&#xff0c;当你导入Druid的依赖时&#xff0c;它已经包含了对J…...

mysql(二)SQL语句

目录 一、SQL语句类型 二、数据库操作 三、数据类型 四、创建 五、查看 六、更改 七、增、删、改、查 八、查询数据 一、SQL语句类型 SQL语句类型&#xff1a; DDL DDL&#xff08;Data Definition Language&#xff0c;数据定义语言&#xff09;&#xff1a;用于…...

Unity自定义后处理——Tonemapping色调映射

大家好&#xff0c;我是阿赵。   继续介绍屏幕后处理&#xff0c;这一期介绍一下Tonemapping色调映射 一、Tone Mapping的介绍 Tone Mapping色调映射&#xff0c;是一种颜色的映射关系处理&#xff0c;简单一点说&#xff0c;一般是从原始色调&#xff08;通常是高动态范围&…...

Redis学习 知识总结 一

Redis学习 知识总结 一 1 Redis初识1.1 Redis八大特性1.2 redis使用场景1.3 Docker安装redis 2 API的理解和使用2.1 通用命令2.2 字符串&#xff08;String&#xff09;类型2.3 哈希&#xff08;Hash&#xff09;类型2.4 有序列表&#xff08;list&#xff09;2.5 集合&#xf…...

Webpack5 vue-loader和VueLoaderPlugin

文章目录 vue-loader和VueLoaderPlugin的作用vue-loader具体使用方式注意事项 vue-loader和VueLoaderPlugin的作用 .vue 文件是用户用 HTML-like 的语法编写的 Vue 组件。每个vue 文件都包括三部分 , VueLoaderPlugin 是一个解析 Vue.js 的插件&#xff0c;用于在 webpack 构…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...