【设计模式深度剖析】【7】【行为型】【观察者模式】

👈️上一篇:中介者模式    |   下一篇:备忘录模式👉️

设计模式-专栏👈️

---

文章目录

  • 观察者模式
    • 英文原文
    • 直译
    • 如何理解?
  • 观察者模式的角色
    • 类图
    • 代码示例
  • 观察者模式的应用
    • 观察者模式的优点
    • 观察者模式的缺点
    • 观察者模式的使用场景

观察者模式

观察者模式Observer Pattern

观察者(Observer)也称发布-订阅(Publish-Subscribe),依赖(Dependents)。

观察者模式就像是一群订阅了报纸的读者,每当报纸有新版发布(状态更新),就会自动送到这些读者的手中,读者们可以根据自己的兴趣选择阅读哪些内容。这样,读者和报纸之间形成了一种灵活、低耦合的订阅-发布关系。

英文原文

The Observer Design Pattern is a behavioral design patternthat defines a one-to-many dependency between objects so that when one object (the subject) changes state, all its dependents (observers) are notified and updated automatically.

直译

观察者设计模式(Observer Design Pattern)是一种行为设计模式,它定义了对象之间的一对多依赖关系,以便当一个对象(主题)改变其状态时,其所有依赖者(观察者)都能得到通知并自动更新。

如何理解?

观察者模式就像是一群朋友在关注一个公告板。公告板是被观察者,而朋友们是观察者。当公告板上的内容发生变化(比如有新的活动通知)时,所有关注这个公告板的朋友们(观察者)都会收到通知,并根据通知的内容做出相应的反应(比如参加活动)。这样,即使公告板的内容经常变化,朋友们也不需要一直盯着它看,只要他们关注了公告板,就能在第一时间得到通知。这种模式不仅方便了朋友们获取信息,也减轻了公告板的负担。

观察者模式的角色

观察者模式通常包含以下几个角色:

  1. Subject(主题/被观察者):它知道有哪些观察者对其感兴趣,并提供了一个接口让观察者能注册自己、移除自己以及通知它们。
  2. Observer(观察者):为那些在主题状态改变时需要获得通知的对象定义一个更新接口。
  3. ConcreteSubject(具体主题):保存有关状态的信息,并提供一个接口供观察者查询状态、注册和移除自己。
  4. ConcreteObserver(具体观察者):实现观察者接口,以便在主题的状态发生改变时得到更新。

类图

在这里插入图片描述

代码示例

package com.polaris.designpattern.list3.behavioral.pattern07.observer.classicdemo;import java.util.ArrayList;
import java.util.List;interface Observer {void update(String message);
}interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers(String message);
}class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers(String message) {for (Observer observer : observers) {observer.update(message);}}// 这里可以添加其他方法来改变状态  public void setState(String state) {// 状态改变时,通知所有观察者  notifyObservers("Subject state has changed to: " + state);}
}class ConcreteObserver implements Observer {private String name;public ConcreteObserver(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + " has been notified: " + message);}
}public class ObserverPatternDemo {public static void main(String[] args) {Subject subject = new ConcreteSubject();System.out.println("registerObserver: Observer 1, Observer 2...");Observer observer1 = new ConcreteObserver("Observer 1");Observer observer2 = new ConcreteObserver("Observer 2");subject.registerObserver(observer1);subject.registerObserver(observer2);System.out.println("change subject state...");// 改变主题状态,这将触发所有注册的观察者的update方法  ((ConcreteSubject) subject).setState("New state");// 移除一个观察者System.out.println("remove observer1...");subject.removeObserver(observer1);System.out.println("change subject state...");// 再次改变主题状态,只会通知未移除的观察者  ((ConcreteSubject) subject).setState("Another new state");}
}/* Output:
registerObserver: Observer 1, Observer 2...
change subject state...
Observer 1 has been notified: Subject state has changed to: New state
Observer 2 has been notified: Subject state has changed to: New state
remove observer1...
change subject state...
Observer 2 has been notified: Subject state has changed to: Another new state
*///~

上面示例当主题的状态改变时,所有注册的观察者都会收到通知并更新它们的状态。当某个观察者被移除后,它将不再收到通知。

观察者模式的应用

  1. 图形用户界面(GUI)开发:在GUI中,当用户与界面上的元素(如按钮、文本框)进行交互时,这些元素的状态可能会发生变化。观察者模式可以用于将这些状态变化通知给相应的观察者,触发相应的操作或更新界面。
  2. 消息通知系统:在聊天应用、社交媒体平台等需要实时消息传递的场景中,观察者模式可以实现消息的订阅与发布。当有新消息发布时,订阅该消息的观察者将收到通知并进行处理。
  3. 股票市场:股票交易所可以充当被观察者,而股票交易员可以充当观察者。当股票的价格、交易量等发生变化时,交易员将接收到通知并采取相应的行动。
  4. 日志记录系统:日志记录器可以充当被观察者,而观察者可以是日志分析器、报警系统等。当日志发生变化时,观察者将收到通知并执行相应的操作,如生成报告、发送警报等。

观察者模式的优点

  1. 解耦:观察者和被观察者是抽象耦合的,降低了它们之间的依赖关系,使得系统更加灵活和可扩展。
  2. 广播通信:支持一对多的依赖关系,简化了系统设计。
  3. 满足开闭原则:增加新的具体观察者或观察目标时,无需修改原有系统代码。

观察者模式的缺点

  1. 性能问题:如果一个被观察者对象有很多的直接和间接的观察者,将所有的观察者都通知到会花费很多时间,可能导致性能下降。
  2. 循环依赖问题:如果观察者和观察目标之间存在循环依赖,可能导致系统崩溃。
  3. 缺乏细节:观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

观察者模式的使用场景

  1. 当一个对象的改变需要同时改变其他对象时:可以使用观察者模式,将需要改变的对象作为观察者,将发生变化的对象作为被观察者。
  2. 当一个对象必须通知其他对象,但又不希望这些对象与它形成紧密耦合时:通过观察者模式,可以实现对象之间的松耦合关系。

---

👈️上一篇:中介者模式    |   下一篇:备忘录模式👉️

设计模式-专栏👈️

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

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

相关文章

PyTorch 张量数据类型

【数据类型】Python 与 PyTorch 常见数据类型对应&#xff1a; 用 a.type() 获取数据类型&#xff0c;用 isinstance(a, 目标类型) 进行类型合法化检测 >>> import torch >>> a torch.randn(2,3) >>> a tensor([[-1.7818, -0.2472, -2.0684],[ 0.…

分布式文件存储 - - - MinIO从入门到飞翔

MinIO从入门到飞翔 文章目录 MinIO从入门到飞翔0、前言1、分布式文件系统2、MinIO 介绍3、 MinIO安装&#xff08;docker&#xff09;4、基本概念5、通过代码上传文件到MinIO6、封装MinIO为starter7、在其他项目中集成封装好的模块 0、前言 对象存储是一种数据存储架构&#x…

C/C++中内存开辟与柔性数组

C/C中内存的开辟 在C中&#xff0c;我们都知道有三个区&#xff1a; 1. 栈区&#xff08;stack&#xff09;&#xff1a;在执行函数时&#xff0c;函数内局部变量的存储单元都可以在栈上创建&#xff0c;函数执行结 束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指…

Mac vscode could not import github.com/gin-gonic/gin

问题背景&#xff1a; 第一次导入一个go的项目就报红 问题分析&#xff1a; 其实就是之前没有下载和导入gin这个web框架包 gin是一个golang的微框架&#xff0c;封装比较优雅&#xff0c;API友好&#xff0c;源码注释比较明确。 问题解决&#xff1a; 依次输入以下命令。通…

Flink作业执行之 2.算子 StreamOperator

Flink作业执行之 2.算子 StreamOperator 前文介绍了Transformation创建过程&#xff0c;大多数情况下通过UDF完成DataStream转换中&#xff0c;生成的Transformation实例中&#xff0c;核心逻辑是封装了SimpleOperatorFactory实例。 UDF场景下&#xff0c;DataStream到Transf…

Windows修改CMD窗口编码为UTF-8

windows下的cmd的默认编码是GBK编码&#xff0c;有时可能造成乱码问题&#xff0c;下面是我找到的两种更换编码方式为UTF-8的方法。 1、临时修改 &#xff08;1&#xff09;先进入cmd命令窗口&#xff08;快捷键win键R&#xff09; &#xff08;2&#xff09;直接输入“chcp…

复数乘法IP核的使用

一、IP核解析 这一部分参考自&#xff1a;FPGA IP之算数运算IP(1)_哔哩哔哩_bilibili IP核设置也是先僵硬复制up主的配置&#xff0c;后续再灵活变通。 在这张图片中&#xff0c;我们看到的是一个“Complex Multiplier (6.0)” IP 核的配置界面。以下是各个配置参数的详细说明…

部署LVS—DR群集

1、LVS-DR工作流向分析 &#xff08;1&#xff09;客户端发送请求到 Director Server&#xff08;负载均衡器&#xff09;&#xff0c;请求的数据报文&#xff08;源 IP 是 CIP,目标 IP 是 VIP&#xff09;到达内核空间。 &#xff08;2&#xff09;Director Server 和 Real Se…

Mongodb使用$pop删除数组中的元素

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第67篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题&#xff0c;欢迎在文章下面点个赞&#xff0c;或者关…

给文件夹加密的最简单方法

安当TDE透明加密针对文件夹数据加密的保护方案主要包括以下几个方面&#xff1a; 1. 透明加密机制&#xff1a; 用户无需关心数据的加密和解密过程&#xff0c;操作文件夹时就像处理普通数据一样。加密和解密操作在后台自动进行&#xff0c;对用户和应用程序透明。 2. 高性能加…

MySQL查询数据库中所有表名表结构及注释以及生成数据库文档

MySQL查询数据库中所有表名表结构及注释 生成数据库文档在后面&#xff01;&#xff01;&#xff01; select t.TABLE_COMMENT -- 数据表注释 , c.TABLE_NAME -- 表名称 , c.COLUMN_COMMENT -- 数据项 , c.COLUMN_NAME -- 英文名称 , -- 字段描述 , upper(c.DATA_TYPE) as …

SortTable.js + vxe-table 实现多条批量排序

环境: vue3+vxe-table+sorttable.js 功能: 实现表格拖动排序,支持单条排序,多条排序 实现思路: sorttable.js官网只有单条排序的例子,网上也都是简单的使用,想要实现多条排序,就要结合着表格的复选框功能,在对其勾选的行统一计算! 最终效果: 实现代码 <template>…

网络数据包抓取与分析工具wireshark的安及使用

WireShark安装和使用 WireShark是非常流行的网络封包分析工具&#xff0c;可以截取各种网络数据包&#xff0c;并显示数据包详细信息。常用于开发测试过程中各种问题定位。 1 任务目标 1.1 知识目标 了解WireShark的过滤器使用,通过过滤器可以筛选出想要分析的内容 掌握Wir…

分享一个 .NET Core 使用选项方式读取配置内容的详细例子

前言 在 .NET Core 中&#xff0c;可以使用选项模式&#xff08;Options Pattern&#xff09;来读取和管理应用程序的配置内容。 选项模式通过创建一个 POCO&#xff08;Plain Old CLR Object&#xff09;来表示配置选项&#xff0c;并将其注册到依赖注入容器中&#xff0c;方…

使用 Oracle SQL Developer 导入数据

使用 Oracle SQL Developer 导入数据 1. 导入过程 1. 导入过程 选择要导入数据的表&#xff0c; 然后单击右键&#xff0c;选择"导入数据"&#xff0c; 浏览本地文件&#xff0c;选择正确的工作表&#xff0c; 按默认&#xff0c; 按默认&#xff0c; 根据情况修改&…

解决MacOS docker 拉取镜像慢的问题

docker官网&#xff1a;https://docker.p2hp.com/get-started/index.html 下载完成之后&#xff0c;拉取镜像速度慢&#xff0c;问题如下&#xff1a; 解决方法 配置阿里源&#xff1a;https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors在docker desktop里面设置…

go的netpoll学习

go的运行时调度框架简介 Go的运行时&#xff08;runtime&#xff09;中&#xff0c;由调度器管理&#xff1a;goroutine&#xff08;G&#xff09;、操作系统线程&#xff08;M&#xff09;和逻辑处理器&#xff08;P&#xff09;之间的关系 以实现高效的并发执行 当一个gorout…

独辟蹊径:我是如何用Java自创一套工作流引擎的(上)

作者&#xff1a;后端小肥肠 创作不易&#xff0c;未经允许严谨转载。 目录 1. 前言 2. 我为什么要自创一套工作流引擎 3. 表结构设计及关系讲解 3.1. 流程类别business_approval_workflow 3.1.1. 表结构 3.1.2. 表关系说明 3.2. 流程定义business_approval_workflow_de…

LVS+Keepalived NGINX+Keepalived 高可用群集实战部署

Keepalived及其工作原理 Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案&#xff0c;可以解决静态路由出现的单点故障问题。 VRRP协议&#xff08;虚拟路由冗余协议&#xff09; 是针对路由器的一种备份解决方案由多台路由器组成一个热备组&#xff0c;通过共用的…

Linux:基础IO(二.缓冲区、模拟一下缓冲区、详细讲解文件系统)

上次介绍了&#xff1a;Linux&#xff1a;基础IO&#xff08;一.C语言文件接口与系统调用、默认打开的文件流、详解文件描述符与dup2系统调用&#xff09; 文章目录 1.缓冲区1.1概念1.2作用与意义 2.语言级别的缓冲区2.1刷新策略2.2具体在哪里2.3支持格式化 3.自己来模拟一下缓…