【设计模式】设计模式之观察者模式

文章目录

  • 观察者模式
  • 什么是观察者模式
  • 引入
  • 组成
  • UML图
  • 代码实现
    • 1. 定义观察者接口
    • 2. 定义主题接口
    • 3. 实现具体观察者
    • 4. 实现具体被观察者
    • 5.测试
  • 应用场景
  • 优点
  • 缺点

观察者模式

什么是观察者模式

观察者模式(Observer Pattern)是一种设计模式

它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象

使得当一个对象的状态发生改变时,其依赖的其他对象会被自动通知和更新

引入

假如你有两种类型的对象: 顾客商店 。 顾客对某个产品非常感兴趣 , 而该产品很快将会在商店里出售。顾客可以每天来商店看看产品是否到货。 但如果商品尚未到货时, 绝大多数来到商店的顾客都会空手而归。因此,每次产品到货时, 商店可以向订阅的顾客发送邮件。 这样, 顾客就无需反复前往商店

假设有一个微信公众号,当微信公众号发布新文章时,所有关注的用户都会收到推送。

组成

由以下四部分组成:

  1. Subject:抽象主题(抽象被观察者)

    抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者

    抽象主题提供一个接口,可以增加和删除观察者对象。

  2. Concretesubject:具体主题(具体被观察者)

    该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。

  3. observer:抽象观察者(观察者的抽象类)

    它定义了一个更新接口,使得在得到主题更改通知时更新自己.

  4. Concrereobserver:具体观察者

    实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

UML图

image-20240801210047539

  1. 具体被观察者 会通过notify方法通过遍历List集合向其他对象发送值得关注的事件。 事件会在发布者自身状态改变或执行特定行为后发生。 发布者中包含一个允许新订阅者加入和当前订阅者离开列表的订阅构架。
  2. 观察者 接口声明了通知接口。 在绝大多数情况下, 该接口仅包含一个 update更新方法。 该方法可以拥有多个参数, 使发布者能在更新时传递事件的详细信息。
  3. 具体观察者 可以执行一些操作来回应发布者的通知。 所有具体订阅者类都实现了同样的接口, 因此发布者不需要与具体类相耦合。

代码实现

1. 定义观察者接口

// 抽象观察者
public interface Observer {void update(String message);
}

2. 定义主题接口

// 抽象主题角色类
public interface Subject {// 添加订阅者(添加观察者对象)void attach(Observer observer);//删除订阅者void detach(Observer observer);//通知订阅者更新消息void notify(String message);
}

3. 实现具体观察者

public class User implements Observer {private String name;public User(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + "接收到:" + message);}
}

4. 实现具体被观察者

// 具体主题角色类
public class SubscriptionSubject implements Subject {// 定义一个集合存储观察者对象 观察者集合private List<Observer> userList = new ArrayList<>();@Overridepublic void attach(Observer observer) {userList.add(observer);}@Overridepublic void detach(Observer observer) {userList.remove(observer);}@Overridepublic void notify(String message) {//遍历集合通知观察者for (Observer observer : userList) {observer.update(message);}}
}

5.测试

package com.feng.observer;public class Client {public static void main(String[] args) {// 1.创建被观察者对象SubscriptionSubject subject = new SubscriptionSubject();// 2.创建用户对象User user1 = new User("用户1");User user2 = new User("用户2");User user3 = new User("用户3");// 3.进行订阅subject.attach(user1);subject.attach(user2);subject.attach(user3);// 4.被观察者发布subject.notify("公众号更新了");}
}

image-20240801212440080

应用场景

  1. 当一个对象状态的改变需要改变其他对象,或实际对象是事先未知的或动态变化的时,可使用观察者模式。
  2. 当应用中的一些对象必须观察其他对象时,可使用该模式。但仅能在有限时间内或特定情况下使用。

优点

  1. 松耦合:观察者和主题之间是松耦合的。主题只知道观察者实现了一个特定的接口,观察者可以自由变化而不影响主题。
  2. 灵活性:可以在运行时添加或删除观察者,灵活应对需求的变化。

缺点

  1. 通知所有观察者的开销:如果观察者很多,通知所有观察者可能会很耗时。
  2. 可能导致循环依赖:如果两个对象互为观察者,可能会导致循环依赖和死循环。


感谢您的阅读
如有错误烦请指正


参考:

  1. 观察者设计模式 (refactoringguru.cn)
  2. 5.设计模式-行为型模式-观察者模式的概述_哔哩哔哩_bilibili

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

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

相关文章

BTS4140N:高侧电源开关芯片中文数据手册

芯片概述 &#xff1a; BTS4140N是一款智能高压侧电源开关N沟道垂直功率MOSFET&#xff0c;带电荷泵和电流控制输入、采用智能SIPMOS技术单片集成&#xff0c;提供嵌入式保护和诊断功能。 芯片特征描述 电流控制输入短路保护电流限制欠电压时关断过压保护&#xff08;包括负载突…

【mars3d】GraphicLayer遍历添加数据,正确拿到数据

import * as mars3d from "mars3d"export let map // mars3d.Map三维地图对象 export let graphicLayer // 矢量数据图层 export const mapOptions {scene: {center:{"lat":30.577085,"lng":116.885511,"alt":45203.5,"heading&…

Jenkins参数化构建

目录 一. 准备ansible 二. Gitlab新建子项目 三. Jenkins建立任务&#xff0c;进行初步配置 四. 导入nginx主机的公钥 五. 配置ansible执行脚本 六. 构建测试 一. 准备ansible 在jenkins主机中安装ansible [rootjenkins ~]# yum install -y epel-release [rootjenkins…

【学习笔记】Day 6

一、进度概述 1、《地震勘探原理》第二章 2、“DenseNet” 周报分享 二、详情 1、《地震勘探原理》第二章 注&#xff1a;本来的打算是逐章整理&#xff0c;但是在听老师指导后&#xff0c;明晰了学习目的。故学习方法更改为侧重 “刷” 。不求一遍全弄懂&#xff0c…

AI在商品计划领域的应用

在现代商业环境中&#xff0c;AI驱动的商品计划优化已经成为企业有效管理资源和提高利润的关键因素。 市场预测与库存管理 精准市场预测&#xff1a;以某著名零售品牌为例&#xff0c;该品牌引入了一种基于AI的智能分析工具&#xff0c;帮助实现了精准的市场预测与库存管理。根…

【Linux基础】Linux基本指令(一)

目录 前言一&#xff0c; ls指令二&#xff0c;pwd指令三&#xff0c;cd指令3.1 当前目录与上级目录3.2 绝对路径和相对路径3.3 tree指令 四&#xff0c;创建一个普通文件或目录4.1 touch指令4.2 mkdir指令 五&#xff0c;删除目录或文件5.1 rmdir指令5.2 rm 指令 六&#xff0…

细节持续跟新

1.input的自带光标如何去除 2.阻止事件冒泡 3.获取父亲兄弟的innertext 4.画表格 参考博主链接 前端-HTML表格制作_哔哩哔哩_bilibili 美化

不同环境下RabbitMQ的安装-3 操作RabbitMQ

前面两篇从不同环境下RabbitMQ的安装-1 为什么要使用消息服务 到同环境下RabbitMQ的安装-2 ARM架构、X86架构、Window系统环境下安装RabbitMQ介绍了关于如何在ARM架构、X86架构和Window系统下如何安装&#xff0c;各位小伙伴可以根据自己的实际开发场景参考安装。 到本篇是一些…

【ARM】CMSIS 软件标准接口

目录 CMSIS&#xff1a;Cortex Microcontroller Software Interface Standard1. 概述2. CMSIS-Core2.1 概述2.2 关键组件2.3 示例代码2.4 详细解释 3. CMSIS-DSP3.1 概述3.2 关键组件3.3 示例代码3.4 详细解释 4. CMSIS-RTOS4.1 概述4.2 关键组件4.3 示例代码4.4 详细解释 5. C…

【案例40】Apache中mod_proxy模块的使用

NC中间件 应用场景&#xff1a;配置了apache的情况&#xff0c;包括uap集群&#xff0c;配置https等场景下均适用&#xff1b;如果是单机&#xff08;NC单结点情况不存在问题&#xff0c;则不用配置这项; was环境也不用配置此项。&#xff09; 解决方案&#xff1a;按如下两…

Spring Boot 3.x Rest API最佳实践之API设计

本系列教程将会以企业中API基础功能封装为目标&#xff0c;用最新的Spring Boot 3.x版本来逐步搭建和完善Rest API项目基础架构&#xff0c;并结合实际电商项目中API的实现需求来进行最佳实践。如果觉得对你有帮助&#xff0c;记得点赞收藏&#xff0c;关注小卷&#xff0c;后续…

React性能之--如何避免组件重复渲染?

在react中&#xff0c;我们会发现存在组件会重复渲染&#xff0c;虽然说如果项目不大的话&#xff0c;这点影响不大&#xff0c;但是我们还是尽量避免组件渲染比较好&#xff0c;养成好习惯&#xff0c;尽可能让不管是大小项目&#xff0c;都让性能尽可能优化 。那我们如何避免…

Linux/C 高级——Linux命令

从这里开始&#xff0c;我们展开对Linux/c 高级的学习&#xff0c;首先介绍的是在Linux/c高级中&#xff0c;Linux的部分 目录 1.Linux简介 1.1Linux起源 1.2查看系统版本命令 1.3分层结构 1.4系统关机重启命令 2.Linux安装工具 2.1软件包安装 2.1.1软件包的管理机制 …

计算机基础(Windows 10+Office 2016)教程 —— 第6章 电子表格软件Excel 2016(上)

第6章 电子表格软件Excel 2016 6.1 Excel 2016入门6.1.1 Excel 2016 简介6.1.2 Excel 2016 的操作界面组成6.1.3 Excel 2016 的视图方式6.1.4 Excel 2016 的工作簿及其操作6.1.5 Excel 2016 的工作表及其操作6.1.5 Excel 2016 的工作表及其操作6.1.6 Excel 2016 的单元格及其操…

Typora+PicGo-Core(command line)+Gitee 实现上传图片到图床(看这一文就够)

前言 ​ 对于喜欢写Markdown文档的人来说&#xff0c;Typora无疑是一个写作利器&#xff0c;它有别于其他的Markdown软件&#xff0c;不是一边编辑一边渲染&#xff0c;而是即写即渲染&#xff0c;这样对于浏览md文件也非常友好。此外Typora还支持更换主题&#xff0c;在其官网…

【QT】Qt中Websocket的使用

一、WebSocket的定义 WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455&#xff0c;并由RFC7936补充规范。WebSocket API也被W3C定为标准。 WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;…

arcgis(shp)注记转CAD(dwg)文字

arcgis&#xff08;shp&#xff09;注记转CAD&#xff08;dwg&#xff09;文字方法如下&#xff1a; 1、添加shp文件&#xff0c;标注要素&#xff0c;然后选标注转注记 2、 点击文件夹图标打开文件夹&#xff0c;选择保存路径。&#xff08;提前需新建好文件地理数据库、数据…

#java学习笔记(面向对象)----(未完结)

一基础相关知识点&#xff1a; 1. 一个对象的调用 首先我们创建一个Phone类 public class Phone {//成员变量String name;int age;String favourite;//成员方法public void myName(){System.out.println(name);}public void myAge(){System.out.println(age);}public void m…

Flink实时数仓(六)【DWD 层搭建(四)交易域、互动域、用户域实现】

前言 今天的任务是完成 DWD 层剩余的事实表&#xff1b;今年的秋招开得比往年早&#xff0c;所以要抓紧时间了&#xff0c;据了解&#xff0c;今年的 hc 还是不多&#xff0c;要是晚点投铁定寄中寄了&#xff1b; 今天还是个周末&#xff0c;不过记忆里我好像整个大学都没有好好…

山姆.奥特尔曼发文暗示:新模型“草莓“即将发布?

山姆.奥特尔曼发文 山姆.奥特尔曼在今天发布了一条推特,图片中所展示的是已经成熟的几颗草莓。要知道之前的"草莓"事件闹的可是沸沸扬扬,而恰巧山姆.奥特尔曼在此时又发出了一条这样的文章。会不会是刻意的在暗示什么呢? 新的模型即将发布&#xff1f; 山姆.奥特尔曼…