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

文章目录

  • 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更新了博客

观察者设计模式优缺点

观察者模式的优点包括:

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

观察者模式的缺点包括:

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

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

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

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

相关文章

十八章:用于弱监督语义分割的自监督等变注意力机制

0.摘要 图像级弱监督语义分割是一个具有挑战性的问题&#xff0c;近年来得到了深入研究。大多数先进的解决方案利用类激活图&#xff08;CAM&#xff09;。然而&#xff0c;由于全监督和弱监督之间存在差距&#xff0c;CAM几乎无法用作对象掩码。在本文中&#xff0c;我们提出了…

[JAVAee]定时器

目录 定时器的含义 定时器的使用 定时器的解析 ①TaskQueue ​②TimerThread ③Timer 定时器的模拟实现 ①创建Task自定义类型 ②创建TimerThread类 ③Timer类 完整代码 定时器的含义 从名字上看,就是我们通俗理解的那个定时器.设置一定的时间,并在一定的时间后发生…

安卓抓包神奇黄鸟HttpCanary安装配置及使用教程

1、下载安装包 黄鸟抓包下载地址 2、安装下载的apk 3、证书安装问题 vivo手机我安装时打开黄鸟app&#xff0c;会直接弹出&#xff0c;直接安装即可 其他手机&#xff0c;需要去系统设置中安装 3.1 搜索 证书&#xff0c;选择CA证书 3.2 进行本人操作验证 3.3 安装HttpCa…

黄东旭:The Future of Database,掀开 TiDB Serverless 的引擎盖

在 PingCAP 用户峰会 2023 上&#xff0c; PingCAP 联合创始人兼 CTO 黄东旭 分享了“The Future of Database”为主题的演讲&#xff0c; 介绍了 TiDB Serverless 作为未来一代数据库的核心设计理念。黄东旭 通过分享个人经历和示例&#xff0c;强调了数据库的服务化而非服务化…

C语言假期作业 DAY 01

题目 1.选择题 1、执行下面程序&#xff0c;正确的输出是&#xff08; &#xff09; int x5,y7; void swap() { int z; zx; xy; yz; } int main() { int x3,y8; swap(); printf("%d,%d\n"&#xff0c;x, y)…

Android Studio 代码模板插件实现

Android Studio 代码模板插件 背景 可以跳过背景和简述&#xff0c;从模板插件实现开始看. 开发新页面时&#xff0c;原先需要写一堆模板代码。比如用Databinding写列表结构的页面&#xff0c;需要手写以下文件&#xff1a; XxActivity.ktXxFragment.ktXxViewModel.ktXxListA…

基于K8s环境·使用ArgoCD部署Jenkins和静态Agent节点

今天是「DevOps云学堂」与你共同进步的第 47天 第⑦期DevOps实战训练营 7月15日已开营 实践环境升级基于K8s和ArgoCD 本文节选自第⑦期DevOps训练营 &#xff0c; 对于训练营的同学实践此文档依赖于基础环境配置文档&#xff0c; 运行K8s集群并配置NFS存储。实际上只要有个K8s集…

CAD .NET 15.0 企业版 Crack

CAD .NET 15.0 企业版 企业版 企业版 企业版 企业版 Updated: June 14, 2023 | Version 15.0 NEW CAD .NET is a library for developing solutions in .NET environment. It supports AutoCAD DWG/ DXF, PLT and other CAD formats. The library can be used in a wide rang…

C语言之pthread_cond_t信号变化探究总结(八十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

【RabbitMQ(day2)】默认(直连)交换机的应用

文章目录 一、第一种模型&#xff08;Hello World&#xff09;二、第二种模型&#xff08;work queue&#xff09;自动确认机制的后果和公平分配 三、阐述默认交换机 这篇博客是以下资料学后的总结&#xff1a; 不良人的RabbitMQ的教学视频 官方启动教程 RabbitMQ中文文档 一、…

【SQL语句】

目录 一、SQL语句类型 1.DDL 2.DML 3.DLL 4.DQL 二、数据库操作 1.查看 2.创建 2.1 默认字符集 2.2 指定字符集 3.进入 4.删除 5.更改 5.1 库名称 5.2 字符集 三、数据表操作 1.数据类型 1.1 数值类型&#xff08;常见&#xff0c;下同&#xff09; 1.1.1 T…

ChatGPT长文本对话输入方法

ChatGPT PROMPTs Splitter 是一个开源工具&#xff0c;旨在帮助你将大量上下文数据分成更小的块发送到 ChatGPT 的提示&#xff0c;并根据如何处理所有块接收到 ChatGPT&#xff08;或其他具有字符限制的语言模型&#xff09;的方法。 推荐&#xff1a;用 NSDT设计器 快速搭建可…

【QT】Day3

1. 完成闹钟的实现&#xff1a; widgt.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> #include <QTimerEvent> //定时器事件处理函数 #include <QTime> //时间类 #include <QTextToSpeech> //文本转语音类头…

Jmap-JVM(十六)

上篇文章说了ZGC是jdk11加入的&#xff0c;他是未来jvm垃圾收集器的奠定者&#xff0c;满足TB级别内存处理&#xff0c;STW时间保持在10ms以下。 Jmap 我们可以先通过jmap -histo 进程ip 来查看&#xff0c;但是这样看不太清晰&#xff0c;我们可以用这行命令生成一个文件&…

机器学习:GPT3

GPT3 模型过于巨大 GPT3是T5参数量的10倍&#xff01; 训练GPT3的代价是$12百万美元 Zero-shot Ability GPT3的思想是不是能拿掉Fine-tune 只需要给定few-shot或者zero-shot就能干相应的任务了。 few-shot learning&#xff08;no gradient descent&#xff09;&#…

9.python设计模式【外观模式】

内容&#xff1a;为子系统中的一组接口提供一个一致的界面&#xff0c;外观模式定义了一个高层接口&#xff0c;这个接口使得这一个子系统更加容易使用。 角色&#xff1a; 外观&#xff08;facade&#xff09;子类系统&#xff08;subsystem classes&#xff09; UML图 举…

容器化安装环境EFK搭建

容器化安装环境 Docker中安装并启动ElasticSearch 前置配置 第一步&#xff1a;在宿主机上执行echo “net.ipv4.ip_forward1” >>/usr/lib/sysctl.d/00-system.conf 2.第二步&#xff1a;重启network和docker服务 [rootlocalhost /]# systemctl restart network &&…

使用低代码开发,需要注意哪些?

低代码平台的历史相对较短&#xff0c;大约始于 2000 年初&#xff0c;源于快速应用程序开发工具。随着低代码平台和工具的日益普及和优势&#xff0c;它不断发展以满足各种领域和角色的需求。 本文将研究各种低代码和无代码应用程序开发方法、业务用例、挑战和未来预测等。 一…

论文浅尝 | 预训练Transformer用于跨领域知识图谱补全

笔记整理&#xff1a;汪俊杰&#xff0c;浙江大学硕士&#xff0c;研究方向为知识图谱 链接&#xff1a;https://arxiv.org/pdf/2303.15682.pdf 动机 传统的直推式(tranductive)或者归纳式(inductive)的知识图谱补全(KGC)模型都关注于域内(in-domain)数据&#xff0c;而比较少关…

UEditor 百度富文本编辑器使用 遇到问题

小小吐槽 碰到前后不分离项目&#xff0c;富文本使用的UEdtior UEditor 点击上传图片转base64 在ueditor.all.js文件中找到这个 callback()函数 这里使用根据图片的url转成base64 UEditore 粘贴图片转base64 UEditor回显图片&#xff08;base64&#xff09; 把ueditor.all…