16、设计模式之观察者模式(Observer)

一、什么是观察者模式
观察者模式属于行为型模式。在程序设计中,观察者模式通常由两个对象组成:观察者和被观察者。当被观察者状态发生改变时,它会通知所有的观察者对象,使他们能够及时做出响应,所以也被称作“发布-订阅模式”。

二、特点

优点:

被观察者和观察者对象之间不需要知道对方的具体实现,只需要知道对方的接口,避免了紧耦合的关系。
由于被观察者对象并不关心具体的观察者是谁,所以在程序运行的过程中,可以动态地增加或者删除观察者对象,增加了灵活性。
符合开闭原则,当需要添加新的观察者时,只需要添加一个实现观察者接口的类,而不需要修改被观察者对象的代码。
缺点:

当观察者没有被正确移除时,可能会导致内存泄漏的问题。 实现观察者模式,需要定义多个接口和类,增加了程序的复杂度。
在某些情况下,被观察者和观察者对象之间可能出现循环依赖的问题。

三、组成

抽象被观察者(Subject):定义了一个接口,包含了注册观察者、删除观察者、通知观察者等方法。
具体被观察者(ConcreteSubject):实现了抽象被观察者接口,维护了一个观察者列表,并在状态发生改变时通知所有注册的观察者。
抽象观察者(Observer):定义了一个接口,包含了更新状态的方法。
具体观察者(ConcreteObserver):实现了抽象观察者接口,存储了需要观察的被观察者对象,并在被观察者状态发生改变时进行相应的处理。

四、应用场景
4.1 生活场景
拍卖的时候,拍卖师是观察者,价格是被观察者。拍卖师观察最高标价,然后通知给其他竞价者竞价。
共享单车:共享单车是被观察者对象,用户是观察者对象。当有新的单车被放置或被租用时,系统会发送给用户通知。
微信公众号:微信公众号是被观察者对象,粉丝是观察者对象。当公众号发布了新的文章或消息时,系统会发送消息给关注该公众号的粉丝。
4.2 程序场景

当一个对象的状态发生改变时,需要通知多个对象做出相应的响应。例如,王者荣耀更新前,会通知所有用户要更新的时间。
当很多对象同时对某一个主题感兴趣时,可以采用观察者模式实现发布-订阅模式。例如,生产者发送消息到消息队列中,并通知所有订阅此队列的消费者进行消费。
数据库开发中,当数据库表中的数据发生变化时,需要通知相关的模块进行更新或其他操作。例如,当用户更新了数据库中的某个记录时,就可以通过观察者模式通知所有注册的监听器进行响应。

五、观察者模式实现
下面以报纸和报纸的订阅者为例,假设你在订阅一份报纸,每天早上送到你门口。你订阅的这份报纸就是被观察者。你和其他的订阅者是观察者。当报纸被送到你门口时,它会自动通知所有的订阅者,让他们知道这份报纸已经到了。

抽象被观察者:Newspaper
具体被观察者:NewspaperImpl
抽象观察者:Subscriber
具体观察者:SubscriberImpl

5.0 UML类图
在这里插入图片描述

5.1 Newspaper
报纸接口,也就是被观察者接口,包含添加、删除、通知三个动作。

/**
 *
 * 报纸接口,即被观察者接口
 */
public interface Newspaper {
    /**
     * 添加订阅者
     * @param subscriber
     */
    void addSubscriber(Subscriber subscriber);
 
    /**
     * 移除订阅者
     * @param subscriber
     */
    void removeSubscriber(Subscriber subscriber);
 
    /**
     * 通知订阅者
     * @param message
     */
    void notifySubscribers(String message);
}

5.2 NewspaperImpl
报纸接口Newspaper的实现类,维护了一个订阅者列表,当报纸到达时会通知所有订阅者。

import java.util.ArrayList;
import java.util.List;
/**
 * 
 * 报纸实现类
 */
public class NewspaperImpl implements Newspaper{
    //订阅者集合
    List<Subscriber> subscribers = new ArrayList<>();
    //添加订阅者
    @Override
    public void addSubscriber(Subscriber subscriber) {
        subscribers.add(subscriber);
    }
    //移除订阅者
    @Override
    public void removeSubscriber(Subscriber subscriber) {
        subscribers.remove(subscriber);
    }
    //通知订阅者
    @Override
    public void notifySubscribers(String message) {
        for (Subscriber s : subscribers) {
            s.update(message);
        }
    }
}

5.3 Subscriber
订阅者接口

/**
 * 
 * 订阅者(即观察者)接口
 */
public interface Subscriber {
    void update(String message);
}

5.4 SubscriberImpl
订阅者接口的实现类,用于接收报纸到达的通知。

import lombok.AllArgsConstructor;
import lombok.Data;
 
/**
 *
 * 具体订阅者
 */
@Data
@AllArgsConstructor
public class SubscriberImpl implements Subscriber{
    private String name;
 
    @Override
    public void update(String message) {
        System.out.println(name + "---接到消息: " + message);
    }
}

5.5 测试
测试代码中,创建了一个NewspaperImpl对象,然后注册了两个订阅者(李老头、王奶奶),执行了两次通知,第一次通知,李老头和王奶奶都收到了消息,第二次通知前,移除了李老头这个订阅者,只有王奶奶收到了通知。

@SpringBootTest
public class TestObserver {
    @Test
    void testObserver(){
        Newspaper newspaper = new NewspaperImpl();
        Subscriber li = new SubscriberImpl("李老头");
        Subscriber wang = new SubscriberImpl("王奶奶");
        //李老头和王奶奶订阅了报纸
        newspaper.addSubscriber(li);
        newspaper.addSubscriber(wang);
        //报纸到了,通知订阅者
        newspaper.notifySubscribers("今天的报纸到了!!!");
        //李老头取消订阅了,移除
        newspaper.removeSubscriber(li);
 
        newspaper.notifySubscribers("明天的报纸还是这个点到!!!");
    }
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【git】GitHub仓库没有 Contribution activity

解决方案 检查并更改本地的 git 绑定的邮箱和名字 git config --global user.name "Your New Name" git config --global user.email "yournewemailexample.com"查询方式 git config --global user.name git config --global user.email成功显示

opencv dnn模块 示例(25) 目标检测 object_detection 之 yolov9

文章目录 1、YOLOv9 介绍2、测试2.1、官方Python测试2.1.1、正确的脚本2.2、Opencv dnn测试2.2.1、导出onnx模型2.2.2、c测试代码 2.3、测试统计 3、自定义数据及训练3.1、准备工作3.2、训练3.3、模型重参数化 1、YOLOv9 介绍 YOLOv9 是 YOLOv7 研究团队推出的最新目标检测网络…

Spring Cloud Alibaba微服务从入门到进阶(三)

Spring Cloud Alibaba是spring Cloud的子项目 Spring Cloud Alibaba的主要组件&#xff08;红框内是开源的&#xff09; Spring Cloud是快速构建分布式系统的工具集&#xff0c; Spring Cloud提供了很多分布式功能 Spring Cloud常用子项目 项目整合 Spring Cloud Alibaba …

开源导出html表格项目-easyHtml

开源导出html表格项目-easyHtml 背景介绍 背景 项目的由来&#xff0c;在面试的过程中&#xff0c;发现这个需求&#xff08;导出html表格&#xff09;比较常见&#xff0c;同时也引起我的兴趣&#xff0c;所以就有了开源项目easyHtml第一个版本 介绍 功能 支持自定义表格标…

Linux 配置ssh、scp、sftp免密登录

SSH&#xff08;Secure Shell&#xff09;是一种安全的远程登录协议&#xff0c;它使用客户端-服务器架构促进2个系统之间的安全通信&#xff0c;并允许用户远程登录服务器。在某些高可用环境下&#xff0c;服务器之间可能还需要配置免密互信&#xff0c;即基于密钥验证登录。 …

vue3 + antd二次封装a-table组件

前置条件 vue版本 v3.3.11 ant-design-vue版本 v4.1.1 内容梗概 二次封装a-table组件&#xff0c;大大提高工作效率和降低项目维护成本&#xff1b; 先看效果图 代码区域 utils.js文件 // 用于模拟接口请求 export const getRemoteTableData (data [], time 1000) >…

STM32第八节:位带操作——GPIO输出和输入

前言 我们讲了GPIO的输出&#xff0c;虽然我们使用的是固件库编程&#xff0c;但是最底层的操作是什么呢&#xff1f;对&#xff0c;我们学习过51单片机的同学肯定学习过 sbit 修改某一位的高低电平&#xff0c;从而实现对于硬件的控制。那么我们现在在STM32中有没有相似的操作…

【数据结构】Set的使用

文章目录 一、Set的使用1.Set的常用方法&#xff1a;1.boolean add(E e)2.void clear()3.boolean contains(Object o)4.boolean remove(Object o)5.int size()6.boolean isEmpty()7.Object[] toArray()8.boolean containsAll(Collection<?> c)9.boolean addAll(Collecti…

学习Vue(1)环境搭建与运行一个vue项目

下载node.js 下载地址&#xff1a;下载 | Node.js 中文网 安装 双击下载好的安装文件&#xff0c;选择安装路径即可。 安装完成&#xff0c;输入命令&#xff1a;nodel -v&#xff0c;查看版本&#xff0c;正常显示版本即安装成功。 自定义全局安装路径和缓存路径&#xff0…

SpringCloud-深度理解ElasticSearch

一、Elasticsearch概述 1、Elasticsearch介绍 Elasticsearch&#xff08;简称ES&#xff09;是一个开源的分布式搜索和分析引擎&#xff0c;构建在Apache Lucene基础上。它提供了一个强大而灵活的工具&#xff0c;用于全文搜索、结构化搜索、分析以及数据可视化。ES最初设计用…

用Origin快速拟合荧光寿命、PL Decay (TRPL)数据分析处理

需要准备材料&#xff1a;Origin、PL Decay数据txt文件 首先打开Origin画图软件 导入数据&#xff0c;按照下图箭头操作直接导入 双击你要导入的PL Decay的txt数据文件&#xff0c;然后点OK 继续点OK 数据导入后首先删除最大光子数之前的无效数据&#xff0c;分析的时候用…

每天五分钟计算机视觉:图像数据不足带来的问题和解决办法

本文重点 在当今的数字时代,图像数据的应用已经渗透到各个领域,包括但不限于计算机视觉、机器学习、自动驾驶、医疗诊断等。然而,当图像数据不足时,会引发一系列问题,对相关应用产生负面影响。 尤其是计算机视觉领域,图像数据尤为珍贵和稀缺,如果计算机视觉的任务中,如…

政务云安全风险分析与解决思路探讨

1.1概述 为了掌握某市政务网站的网络安全整体情况&#xff0c;在相关监管机构授权后&#xff0c;我们组织人员抽取了某市78个政务网站进行安全扫描&#xff0c;通过安全扫描&#xff0c;对该市政务网站的整体安全情况进行预估。 1.2工具扫描结果 本次利用漏洞扫描服务VSS共扫…

基于Spring Boot的疗养院管理系统的设计与实现

传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装疗养院管理系统软件来发挥其高效地信息处理的作用&#xff0c;可以…

使用html+css制作一个发光立方体特效

使用htmlcss制作一个发光立方体特效 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Documen…

【机器学习300问】36、什么是集成学习?

一、什么是集成学习&#xff1f; &#xff08;1&#xff09;它的出现是为了解决什么问题&#xff1f; 提高准确性&#xff1a;单个模型可能对某些数据敏感或者有概念偏见&#xff0c;而集成多个模型可以提高预测的准确性。让模型变稳定&#xff1a;一些模型&#xff0c;如决策…

Css基础——溢出文字省略号表达

1. 单行文本溢出显示省略号&#xff1a; 1.1、方法&#xff1a; 1. 先强制一行内显示文本*/ white-space: nowrap; &#xff08; 默认 normal 自动换行&#xff09; 2. 超出的部分隐藏*/ overflow: hidden; 3. 文字用省略号替代超出的部分*/ text-overflow: ellipsis; 1.2、代…

【他山之石】BlueLM蓝心大模型的落地

note 预训练&#xff1a;我们采用了混合精度训练以及梯度缩放策略&#xff0c;因为这可以减少训练周期&#xff0c;训练周期较少会节省模型训练所需的时间和资源。选择回放训练能够让模型定向学会一类知识信息。Loss 预测确保在训练过程前对损失进行估计&#xff0c;以保证训练…

javaweb day16 mysql

mysql 安装&#xff1a; 企业开发使用方法 安装虚拟机代替服务器 数据模型 创建数据库 写法 sql简介

KNN算法对鸢尾花进行分类:添加网格搜索和交叉验证

优化——添加网格搜索和交叉验证 from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection imp…