23种设计模式-观察者(Observer)设计模式

文章目录

  • 一.什么是观察者模式?
  • 二.观察者模式的结构
  • 三.观察者模式的应用场景
  • 四.观察者模式的优缺点
  • 五.观察者模式的实现(C++示例)
  • 六.观察者模式的实现(JAVA示例)
  • 七.代码解释
  • 八.总结

类图: 观察者设计模式类图

一.什么是观察者模式?

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象之间的一对多关系。即一个对象(称为“主题”)状态发生改变时,会自动通知依赖它的其他对象(称为“观察者”)。这种模式在很多场景中都非常适用,比如发布-订阅系统、事件监听、界面刷新等。
 观察者模式的特点是松耦合:观察者和主题不需要彼此了解细节,只需按照约定进行交互,这种设计提升了代码的可维护性和可扩展性

二.观察者模式的结构

  • Subject(主题):又称被观察者,用于存储和管理观察者,并在自身状态变化时通知观察者。
  • Observer(观察者):观察者接口,用于定义更新方法,所有观察者实现该接口。
  • ConcreteSubject(具体主题):继承自主题接口,实现状态管理和通知观察者的具体逻辑。
  • ConcreteObserver(具体观察者):实现观察者接口,通过获取主题更新,执行相应的行为。

三.观察者模式的应用场景

  1. 事件监听:用户在UI界面点击按钮时,按钮组件通过通知事件监听器实现某种交互。
  2. 数据变化通知:在数据变化时,多个视图自动更新显示。例如,股票价格变化时,订阅者自动更新价格显示。
  3. 发布-订阅系统:发布者更新数据时,通知订阅的所有观察者,实现自动信息推送。

四.观察者模式的优缺点

  • 优点

    • 解耦:主题与观察者之间的耦合度较低,可以独立扩展。
    • 自动通知:当主题状态发生变化时,无需手动通知每个观察者。
  • 缺点

    • 通知耗时:当观察者数量较多或更新频繁时,可能会导致性能问题。
    • 顺序依赖:如果通知是同步进行的,通知的顺序会影响整个流程。

五.观察者模式的实现(C++示例)

#include <iostream>
#include <vector>
#include <string>// 观察者接口
class Observer {
public:virtual void update(const std::string &message) = 0;
};// 主题接口
class Subject {
public:virtual void addObserver(Observer* observer) = 0;virtual void removeObserver(Observer* observer) = 0;virtual void notifyObservers() = 0;
};// 具体主题类
class ConcreteSubject : public Subject {
private:std::vector<Observer*> observers;std::string message;public:void setMessage(const std::string &newMessage) {message = newMessage;notifyObservers();  // 通知所有观察者}void addObserver(Observer* observer) override {observers.push_back(observer);}void removeObserver(Observer* observer) override {observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());}void notifyObservers() override {for (Observer* observer : observers) {observer->update(message);}}
};// 具体观察者类
class ConcreteObserver : public Observer {
private:std::string name;public:ConcreteObserver(const std::string &observerName) : name(observerName) {}void update(const std::string &message) override {std::cout << "Observer " << name << " received message: " << message << std::endl;}
};// 测试代码
int main() {ConcreteSubject subject;// 创建观察者ConcreteObserver observer1("Observer1");ConcreteObserver observer2("Observer2");// 添加观察者subject.addObserver(&observer1);subject.addObserver(&observer2);// 主题更新并通知观察者subject.setMessage("New message arrived");// 移除观察者并更新主题subject.removeObserver(&observer1);subject.setMessage("Another message");return 0;
}

六.观察者模式的实现(JAVA示例)

import java.util.ArrayList;
import java.util.List;// 抽象观察者类
interface Observer {void update(int state); // 更新方法
}// 具体观察者A
class ConcreteObserverA implements Observer {@Overridepublic void update(int state) {System.out.println("ConcreteObserverA: State updated to " + state);}
}// 具体观察者B
class ConcreteObserverB implements Observer {@Overridepublic void update(int state) {System.out.println("ConcreteObserverB: State updated to " + state);}
}// 抽象主题类
abstract class Subject {protected List<Observer> observers = new ArrayList<>();// 添加观察者public void attach(Observer observer) {observers.add(observer);}// 移除观察者public void detach(Observer observer) {observers.remove(observer);}// 通知所有观察者public void notifyObservers(int state) {for (Observer observer : observers) {observer.update(state);}}
}// 具体主题类
class ConcreteSubject extends Subject {private int state;public int getState() {return state;}public void setState(int state) {this.state = state;System.out.println("ConcreteSubject: State changed to " + state);notifyObservers(state); // 通知观察者}
}// 客户端代码
public class ObserverPatternDemo {public static void main(String[] args) {// 创建具体主题ConcreteSubject subject = new ConcreteSubject();// 创建观察者并订阅Observer observerA = new ConcreteObserverA();Observer observerB = new ConcreteObserverB();subject.attach(observerA);subject.attach(observerB);// 更改状态并通知观察者subject.setState(10);subject.setState(20);// 取消观察者A的订阅subject.detach(observerA);// 再次更改状态subject.setState(30);}
}

七.代码解释

  1. Observer 接口:Observer是一个抽象基类,包含update方法,所有观察者都要实现该方法,以响应主题的通知。
  2. Subject 接口:Subject也是一个抽象基类,提供addObserver、removeObserver和notifyObservers方法,主题通过这些方法管理和通知观察者。
  3. ConcreteSubject 类:这是主题的具体实现类,包含observers向量用于保存观察者。当主题状态改变时,通过调用notifyObservers通知所有观察者。
  4. ConcreteObserver 类:这是观察者的具体实现类。每个观察者都有一个name属性,并在update方法中响应通知。
  5. 测试代码:在main函数中创建了一个主题对象subject,并注册两个观察者对象observer1和observer2。主题更新时,所有观察者都会收到通知。

八.总结

 观察者模式是一种非常实用的设计模式,特别是在需要通知多个对象的场景中非常合适。它让主题和观察者之间实现了低耦合,从而增强系统的灵活性扩展性。通过实现一个通用的观察者接口和主题接口,观察者模式能够很好地应对需求的变化,使得观察者可以随时添加、删除,并根据主题的状态变化而自动更新,从而达到良好的解耦效果。

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

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

相关文章

使用dataGrip连接spark

概述&#xff1a; spark的配置共有5种 1、本地模式 2、集群模式&#xff1a;standalone&#xff0c; yarn&#xff0c;k8s&#xff0c;mesos四种集群模式 spark本身只是一个计算引擎&#xff0c;是没有数据库的&#xff0c;所以说数据需要在hdfs上存放&#xff0c;而数据库就…

前馈神经网络 (Feedforward Neural Network, FNN)

代码功能 网络定义&#xff1a; 使用 torch.nn 构建了一个简单的前馈神经网络。 隐藏层使用 ReLU 激活函数&#xff0c;输出层使用 Sigmoid 函数&#xff08;适用于二分类问题&#xff09;。 数据生成&#xff1a; 使用经典的 XOR 问题作为数据集。 数据点为二维输入&#xff…

《操作系统 - 清华大学》3 -3:连续内存分配:内存碎片与分区的动态分配

文章目录 0. 概述1. 内存碎片问题2. 动态分配3. 首次适配算法4. 最优适配算法5. 最差适配算法 0. 概述 内存分配是操作系统管理过程中很重要的环节&#xff0c;首先需要考虑的是一块连续区域分配的过程&#xff0c;这个过程中会有很多问题&#xff0c;首先比较关注的一个问题是…

[Mysql基础]表的查询

一、表的增删改查 CRUD : Create(创建), Retrieve(读取)&#xff0c;Update(更新)&#xff0c;Delete&#xff08;删除&#xff09; 1.1 插入否则更新 由于 主键 或者 唯一键 对应的值已经存在而导致插入失败 -- 创建一张学生表 CREATE TABLE students (id INT UNSIGNED PR…

Py之pymupdf:基于langchain框架结合pymupdf库实现输出每个PDF页面的文本内容、元数据等

Py之pymupdf:基于langchain框架结合pymupdf库实现输出每个PDF页面的文本内容、元数据等 目录 PyMuPDFLoader类 初始化 属性 方法 __init__(file_path, *, headers=None, extract_images=False, **kwargs) lazy_load() aload() alazy_load() load(**kwargs) load_and…

信息安全工程师(83)Windows操作系统安全分析与防护

一、Windows操作系统安全分析 系统漏洞&#xff1a; Windows操作系统由于其复杂性和广泛使用&#xff0c;可能存在一些已知或未知的漏洞。这些漏洞可能会被黑客利用&#xff0c;进行恶意攻击。微软会定期发布系统更新和补丁&#xff0c;以修复这些漏洞&#xff0c;提高系统的安…

python selenium库的使用:通过兴趣点获取坐标

通过兴趣点获取坐标 from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.common.exceptions import TimeoutException# 保存Cookies到文件&#xff08;可选&#xff09; import pi…

Excel超级处理器:高效实现2种批量生成二维码方式

在Excel数据处理中&#xff0c;二维码的批量生成是一个常见且重要的需求。借助Excel超级处理器这一强大的插件&#xff0c;用户可以轻松实现二维码的两种主要批量生成方式&#xff1a;直接在单元格中显示二维码图片&#xff0c;以及直接生成二维码图片并保存在文件夹中。超级处…

vue+svg圆形进度条组件

vuesvg圆形进度条组件 一、实现思路二、ProgressCircle.vue三、父组件使用四、实现效果 一、实现思路 使用svg的circle元素画两个圆形&#xff0c;一个圆形控制进度&#xff0c;一个绘制底色 二、ProgressCircle.vue 代码示例&#xff1a; <template><!-- 圆形进度…

react+hook+vite项目使用eletron打包成桌面应用+可以热更新

使用Hooks-Admin的架构 Hooks-Admin: &#x1f680;&#x1f680;&#x1f680; Hooks Admin&#xff0c;基于 React18、React-Router V6、React-Hooks、Redux、TypeScript、Vite2、Ant-Design 开源的一套后台管理框架。https://gitee.com/HalseySpicy/Hooks-Adminexe桌面应用…

如何基于Tesseract实现图片的文本识别

在前一篇文章基础上&#xff0c;如何将报告图片中的文本解析出来&#xff0c;最近研究了基于Tesseract的OCR方案&#xff0c;Tesseract OCR是一个开源的OCR引擎&#xff0c;主要结合开源的tesseract和pytesseract&#xff0c;实现了jpg/png等格式图片文本识别&#xff0c;供大家…

Vue中template模板报错

直接<v出现如下模板&#xff0c;出现如下错误 注意两个地方&#xff1a; 1.template里面加一个div标签 2.要写name值 如下图

地质旅游平台推动“旅游+地质”融合发展

2024年元旦假期&#xff0c;哈尔滨文旅市场持续火爆。据哈尔滨市文化广电和旅游局大数据测算&#xff0c;截至1月1日&#xff0c;哈尔滨市累计接待游客304.79万人次&#xff0c;实现旅游总收入59.14亿元&#xff0c;游客接待量与旅游总收入达到历史峰值。 夏有进“淄”赶烤&…

接口文档的编写

接口文档 背景介绍 API&#xff08;Application Programming Interface&#xff09;即应用程序接口。可以认为 API 是一个软件组件或是一个 Web 服务与外界进行的交互的接口。 目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力&#xff0c;而又无需访问源…

Linux源码阅读笔记-V4L2框架基础介绍

V4L2视频设备驱动基础 V4L2 是专门为 Linux 设备设计的整套视频框架&#xff08;其主要核心在 Linux 内核&#xff0c;相当于 Linux 操作系统上层的视频源捕获驱动框架&#xff09;。为上层访问系统底层的视频设备提供一个统一的标准接口。V4L2 驱动框架能够支持多种类型设备&…

机器学习day2-特征工程

四.特征工程 1.概念 一般使用pandas来进行数据清洗和数据处理、使用sklearn来进行特征工程 将任意数据&#xff08;文本或图像等&#xff09;转换为数字特征&#xff0c;对特征进行相关的处理 步骤&#xff1a;1.特征提取&#xff1b;2.无量纲化&#xff08;预处理&#xf…

机器学习 - 为 Jupyter Notebook 安装新的 Kernel

https://ipython.readthedocs.io/en/latest/install/kernel_install.html 当使用jupyter-notebook --no-browser 启动一个 notebook 时&#xff0c;默认使用了该 jupyter module 所在的 Python 环境作为 kernel&#xff0c;比如 C:\devel\Python\Python311。 如果&#xff0c…

SQL面试题——持续增长问题

持续增长我们也可以称之为连续增长,本质上还是连续类的问题,前面我们已经介绍过 SQL面试题——最大连续登陆问题 SQL面试题——球员连续四次得分 SQL面试题——间隔连续问题 SQL面试题——蚂蚁SQL面试题 连续3天减少碳排放量不低于100的用户 你可以看看之前的文章,了解…

w038基于SpringBoot的网上租赁系统设计与实现

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0…

深入探索 Kubernetes 安全容器:Kata Containers 与 gVisor

深入探索Kubernetes安全容器:Kata Containers与gVisor 在Kubernetes的世界里,安全始终是一个不容忽视的话题。随着容器技术的发展,我们对容器安全性的要求也越来越高。本篇文章将深入剖析Kubernetes课程第四十三节的核心主题——“绝不仅仅是安全:Kata Containers与gVisor…