设计模式 - Observer Pattern 观察者模式

news2024/11/24 20:15:01

文章目录

  • 定义
  • 观察者模式的实现构成
    • 构成
    • UML图
  • 观察者模式的代码实现
    • 场景
    • 代码实现
  • 总结
    • 优点
    • 缺点
    • 应用场景
  • 其他设计模式文章:

定义

观察者模式是行为型模式的一种,它定义对象间的一种一对多的依赖关系,使得每当一个对象改变状态,它的所有依赖都会收到通知并且自动更新状态。

简单来说就是:当一个行为发生时传递信息给另外一个用户接收做出相应的处理,它们之间其实没有什么直接的关联。

观察者模式的实现构成

构成

 1. 主题(Subject):抽象主题,提供方法来增加和删除观察者,当自身状态发生改变时,通知所有观察者。
 2. 观察者(Observer):抽象观察者,用于接收主题状态更新的通知。
 3. 具体主题(Concrete Subject):实现主题接口、在其内部状态发生改变时,通知所有注册的观察者。
 4. 具体观察者(Concrete Observer):实现观察者接口、在接收到主题的通知时更新自身状态。

UML图

在这里插入图片描述

观察者模式的代码实现

场景

假设我们有一个股票价格监控系统,不同的模块(图表模块、统计模块和警报模块),它们需要实时更新股票价格信息。当股票价格发生变化时,这些模块就立即可以获取到通知并且可以进行更新显示。

代码实现

观察者接口
// 观察者接口,定义更新方法
interface Observer {
	// 当主题状态变化时调用此方法通知观察者。
    void update(double price);
}
具体观察者
// 具体观察者:图表模块
class ChartDisplay implements Observer {
    @Override
    public void update(double price) {
        System.out.println("图表模块更新股票价格: " + price);
    }
}

// 具体观察者:统计模块
class StatisticsDisplay implements Observer {
    @Override
    public void update(double price) {
        System.out.println("统计模块更新股票价格: " + price);
    }
}

// 具体观察者:警报模块
class AlertSystem implements Observer {
    @Override
    public void update(double price) {
        if (price > 100.0) {
            System.out.println("警报!股票价格超过100元: " + price);
        }
    }
}
主题接口
// 主题接口,定义增加、删除观察者及通知方法,用于管理和通知观察者。
interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}
具体主题
// 具体主题:实现了Subject,用来维护观察者列表并在价格变化时通知所有观察者。
class StockPrice implements Subject {
    private List<Observer> observers;
    private double price;

    public StockPrice() {
        observers = new ArrayList<>();
    }

    @Override
    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(price);
        }
    }

    // 设置新价格并通知观察者
    public void setPrice(double price) {
        this.price = price;
        notifyObservers();
    }
}
客户端代码
// 客户端代码
public class ObserverPatternDemo {
    public static void main(String[] args) {
        // 创建具体主题
        StockPrice stockPrice = new StockPrice();

        // 创建具体观察者
        ChartDisplay chartDisplay = new ChartDisplay();
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay();
        AlertSystem alertSystem = new AlertSystem();

        // 注册观察者
        stockPrice.addObserver(chartDisplay);
        stockPrice.addObserver(statisticsDisplay);
        stockPrice.addObserver(alertSystem);

        // 更新股票价格
        stockPrice.setPrice(95.0);
        System.out.println();

        stockPrice.setPrice(105.0);
    }
}

总结

优点

 1. 解耦:主题只需知道观察者实现了某个接口,不需要知道具体实现细节,双方可以独立变化。
 2. 目标与观察者之间建立了一套触发机制。

缺点

 1. 当观察者对象很多时,通知的发布会花费很长时间,影响程序的效率。
 2. 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

应用场景

 跨系统的消息交换场景,如消息队列,事件总线的处理机制

其他设计模式文章:

  • 设计模式 - Singleton pattern 单例模式
  • 设计模式 - Factory Method 工厂方法
  • 设计模式 - Chain Of Responsibility 责任链模式
  • 设计模式 - Template Method 模板方法
  • 设计模式 - Strategy Pattern策略模式
  • 设计模式 - Observer Pattern 观察者模式

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

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

相关文章

Apache HBase概述(图文并茂~)

HBase概述 1. Why we need HBase &#xff1f; 在大数据时代来临之前&#xff0c;我们通常依赖传统的关系型数据库&#xff08;如RDBMS&#xff09;来处理数据存储和管理。然而&#xff0c;随着数据量的急剧增长和数据结构的多样化&#xff0c;传统数据库系统开始显露出其局限性…

手写一个基于SpringBoot的MVC架构,默认实现CRUD和导入导出功能

文章目录 前言正文一、项目结构二、技术点三、部分核心代码3.1 core-tool 中的核心代码3.1.1 所有实体的通用父类 SuperEntity3.1.2 所有枚举的父接口 BaseEnum3.1.3 所有业务异常的父接口 BaseException 3.2 mvc-tool 中的核心代码3.2.1 CrudController 接口定义3.2.2 默认的C…

文心一言 VS 讯飞星火 VS chatgpt (290)-- 算法导论21.3 3题

三、给出一个包含 m 个 MAKE-SET 、UNION 和 FINDSET 操作的序列(其中有 n 个是 MAKE-SET 操作)&#xff0c;当仅使用按秩合并时&#xff0c;需要 Ω(mlgn) 的时间。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 在并查集&#xff08;Union-Find&#xff09;数…

STM32使用PWM驱动WS2812_RGB灯珠

项目场景&#xff1a; 使用STM32标准库产生PWM实现RGB灯珠控制。 芯片型号&#xff1a;stm32f405rgt6 设计优点&#xff1a;不需要使用定时器中断资源&#xff0c;可以使得STM32在驱动RGB灯珠的同时能够执行其他任务。 RGB灯珠简介 项目所使用的RGB灯珠如下所示&#xff0c;封装…

76. UE5 RPG 实现场景阻挡剔除功能

在俯视角游戏中&#xff0c;我们总会碰到一个问题就是&#xff0c;建筑会遮挡住角色的问题。遇到这种问题有多种解决方案&#xff0c;厂商经常使用的一种方案是&#xff0c;如果角色被遮挡&#xff0c;则使用一种纯色或者增加一些菲涅尔的效果来实现 这种效果我之前在unity内实…

免费使用文心一言会员教程

领取&安装链接&#xff1a;Baidu Comate 领取季卡 有图有真相 原理&#xff1a;百度comate使用文心一言最新的4.0模型。百度comate目前免费使用&#xff0c;可以借助comate达到免费使用4.0模型目的。 如何获得 点击「Baidu Comate 领取季卡 -> 领取权益」&#xff0…

Cesium Model 中的剪裁平面 (ClippingPlane)

Cesium Model 中的剪裁平面 (ClippingPlane) 参考: https://www.cnblogs.com/webgl-angela/p/9197672.html Cesium Model 中的剪裁平面 (ClippingPlane) // 相关类: class ClippingPlaneCollection {} class ClippingPlane {}// 剪裁的整体流程: Model.prototype.update () …

Mathematica训练课(45)-- 一些常用的函数Abs[],Max[]等函数用法

①绝对值函数&#xff1a;Abs[]函数 ②最大值和最小值函数 ③反函数

SAP ATP可用性检查简介

Availability Check,就是可用性检查,指的是要检查一下此物料是否能满足我的需求。 接到一张销售订单(SALES ORDER),客户要求数量为100PC,并且客户要求的出货日期是2024-07-01,此时我们的销售人员肯定会想到底能否出货给客人呢?系统中建立此单时,SAP就会做一个所谓的检…

实验八 T_SQL编程

题目 以电子商务系统数据库ecommerce为例 1、在ecommerce数据库&#xff0c;针对会员表member首先创建一个“呼和浩特地区”会员的视图view_hohhot&#xff0c;然后通过该视图查询来自“呼和浩特”地区的会员信息&#xff0c;用批处理命令语句将问题进行分割&#xff0c;并分…

17859划分准则小结

17859《划分准则》 发布时间&#xff1a;1999.9.13 实施时间&#xff1a;2001.1.1 计算机信息系统安全保护能力的五个等级&#xff1a; 第一级&#xff1a;用户自主保护级 第二级…

Java知识点整理 15 — MyBatis框架

一. 什么是 MyBatis MyBatis 是一款优秀的持久层框架&#xff0c;支持自定义 SQL、存储过程以及高级映射。它免除了几乎所有 JDBC代码以及手动设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO&#xff08;普通老式 Jav…

人脑网络的多层建模与分析

摘要 了解人类大脑的结构及其与功能的关系&#xff0c;对于各种应用至关重要&#xff0c;包括但不限于预防、处理和治疗脑部疾病(如阿尔茨海默病或帕金森病)&#xff0c;以及精神疾病(如精神分裂症)的新方法。结构和功能神经影像学方面的最新进展&#xff0c;以及计算机科学等…

决定佛蒙特州版图的关键历史事件:

​决定佛蒙特州版图的关键历史事件: 1. 早期探险与命名&#xff1a; - 1609年&#xff0c;法国探险家萨缪尔德尚普兰&#xff08;Samuel de Champlain&#xff09;到达了现在的佛蒙特州区域&#xff0c;并探索了尚普兰湖&#xff08;Lake Champlain&#xff09;。他将周围的山…

mwwz库添加对多模板匹配的支持:find_shape_models

多模板匹配的实现只需要对单模板匹配做一些扩展&#xff0c;传入的模板由不同的id表示&#xff0c;在金字塔顶层完成模板的分类&#xff0c;在剩下的金字塔完成对每一类模板的匹配&#xff0c;匹配结果由id标识。测试程序已集成该方法&#xff0c;清除模板后所创建的模板被看作…

Python基于决策树分类模型、支持向量机分类模型、随机森林分类模型和XGBoost分类模型实现月亮数据标签预测项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 在探索机器学习算法的性能与适用性时&#xff0c;我们往往需要依赖于精心设计的人工数据集来测试和验证…

全面对标GPT-4 Turbo,讯飞星火V4.0凭什么?

大数据产业创新服务媒体 ——聚焦数据 改变商业 自从ChatGPT爆火出圈之后&#xff0c;大模型就走上了发展的快车道。 一方面&#xff0c;大模型技术快速演进&#xff0c;Sora为我们打开了视频生成的想象空间&#xff0c;各大厂商争相打破大模型的“模态墙”&#xff0c;长文本…

pytest中的极其重要固件(request)的理解

pytest 是一个非常流行的Python测试框架&#xff0c;它为开发人员提供了丰寴的测试工具和功能。 在pytest中&#xff0c;固件&#xff08;fixture&#xff09;是一种非常核心的概念&#xff0c;用于设置测试前的预条件&#xff0c;清理测试后的环境&#xff0c;或者提供测试过…

什么是DEQ?

DEQ (Delivered Ex Quay, Duty Paid) 是指目的港码头交货 (……指定目的港)。 这种术语规定卖方在指定目的港码头将货物交给买方处置&#xff0c;并且不办理进口清关手续。 DEQ适用范围 DEQ术语仅适用于海运、内河运输或多式联运&#xff0c;并且在目的港码头卸货时使用。如…

RAG 基本流程及处理技巧 with LangChain

LLM 主要存在两个问题&#xff1a;幻想和缺乏领域知识。领域知识缺乏的原因是因为训练 LLM 本身的知识更新慢&#xff0c;对特定领域的知识也没有太细致的输入。 RAG 主要是解决 LLM 缺乏领域知识的问题。底层的逻辑是&#xff1a;把 LLM 作为逻辑推理引擎&#xff0c;而不是信…