设计模式-07 设计模式-观察者模式(Observer Pattern)

设计模式-07 设计模式-观察者模式(Observer Pattern)

1.定义


观察者模式是一种软件设计模式,它定义了一种一对多的依赖关系,其中一个对象(称为“主题”)维护了一个依赖对象的列表(称为“观察者”),并且当主题的状态发生变化时,它会自动通知所有观察者。


2.内涵

换句话说,观察者模式允许对象订阅其他对象并接收有关其状态更改的通知。主题对象负责管理观察者列表并通知它们任何状态更改。

涉及到的相关术语:

主题(Subject):维护观察者列表并通知它们状态更改的对象。
观察者(Observer):订阅主题并接收有关其状态更改的通知的对象。
具体主题(Concrete Subject):实现主题接口并维护具体状态和观察者列表的类。
具体观察者(Concrete Observer):实现观察者接口并定义对主题状态更改的响应的类。


工作原理,当观察者模式使用时:

  • 观察者向主题注册,表示他们有兴趣接收状态更改通知。
  • 主题维护一个观察者列表,其中包含所有已注册的观察者。
  • 当主题的状态发生变化时,它会遍历观察者列表并调用每个观察者的 update() 方法。
  • 观察者收到通知并相应地更新自己的状态。
3.使用案例
#include <iostream>
#include <vector>

// Observer interface
class Observer {
public:
    virtual void update(float temperature, float humidity, float pressure) = 0;
};

// Subject (WeatherStation) class
class WeatherStation {
private:
    float temperature;
    float humidity;
    float pressure;
    std::vector<Observer*> observers;

public:
    void registerObserver(Observer* observer) {
        observers.push_back(observer);
    }

    void removeObserver(Observer* observer) {
        // You can implement the removal logic if needed.
    }

    void notifyObservers() {
        for (Observer* observer : observers) {
            observer->update(temperature, humidity, pressure);
        }
    }

    void setMeasurements(float temp, float hum, float press) {
        temperature = temp;
        humidity = hum;
        pressure = press;
        notifyObservers();
    }
};

// Concrete Observer
class Display : public Observer {
public:
    void update(float temperature, float humidity, float pressure) {
        std::cout << "Display: Temperature = " << temperature
                << "°C, Humidity = " << humidity
                << "%, Pressure = " << pressure << " hPa"
                << std::endl;
    }
};

int main() {
    WeatherStation weatherStation;

    // Create displays
    Display display1;
    Display display2;

    // Register displays as observers
    weatherStation.registerObserver(&display1);
    weatherStation.registerObserver(&display2);

    // Simulate weather data updates
    weatherStation.setMeasurements(25.5, 60, 1013.2);
    weatherStation.setMeasurements(24.8, 58, 1014.5);

    return 0;
}

4.注意事项

观察者模式的优点包括:

  • 松散耦合:观察者和主题是松散耦合的,这意味着它们可以独立更改而不会影响彼此。
  • 可扩展性:可以轻松地向系统中添加或删除观察者,而不会影响主题或其他观察者。
  • 可重用性:观察者模式可以轻松地应用于不同的应用程序和领域。

观察者模式的缺点包括:

  • 性能开销:当主题的状态经常更改时,通知所有观察者可能会产生性能开销。
  • 通知顺序:观察者模式不保证观察者将按特定顺序收到通知。
  • 内存占用:如果有很多观察者订阅主题,主题需要维护一个很大的观察者列表,这可能会导致内存占用增加。

5.最佳实践
  • 使用接口而不是具体类:主题和观察者接口应该用于定义主题和观察者之间的关系,而不是使用具体类。这提高了代码的可重用性和灵活性。
  • 使用弱引用:观察者应该使用弱引用持有对主题的引用。这可以防止循环引用,并允许在观察者不再需要时自动释放它们。
  • 考虑使用事件对象:事件对象可以用来封装状态更改通知。这可以提供更丰富的通知,其中包含有关状态更改的附加信息。
  • 使用主题层次结构:当需要对不同类型的状态更改进行更精细的控制时,可以使用主题层次结构。这允许观察者只订阅他们感兴趣的特定状态更改。


使用观察者模式,需要考虑优化通知性能,如果主题的状态经常更改,可以使用以下技术来优化通知性能:

  • 使用位掩码或标志来跟踪已更改的状态方面。
  • 批量处理观察者通知。
  • 使用异步通知机制,例如消息队列。
  • 使用线程安全:如果主题或观察者可能从多个线程访问,则需要使用线程安全技术,例如互斥锁或原子操作。
  • 考虑使用第三方库:有许多第三方库提供了观察者模式的实现,可以简化其在应用程序中的使用。

6.总结

仅在需要时使用观察者模式。它可能会引入一些开销和复杂性。心中明白清楚地定义观察者订阅和取消订阅的机制。考虑使用观察者模式的变体,例如发布/订阅模式或模型-视图-控制器 (MVC) 模式。在设计观察者模式时,牢记 SOLID 原则(单一职责、开放/封闭、里氏替换、接口隔离和依赖反转)。

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

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

相关文章

vue uniapp 小程序 判断日期是今天(显示时分秒)、昨天、本周的周几、超出本周显示年月日

效果图&#xff1a; util.js /*** 转换时间*/ const messageFormat (datetime) >{ let result "";let currentTime new Date();if(isToday(datetime)){result datetime.substring(11,16);}else if(isYesterday(datetime)){result "昨天";}else if(…

EasyExcel导出带自定义下拉框数据的Excel模板

文章目录 前言&#x1f4dd;一、导入依赖二、创建导出工具1.创建模板实体类2.创建自定义注解3.添加动态选择接口4.EasyExcelUtil工具类 三、导出、导入Excel接口1.导出接口2.导入接口3.导出结果 总结 前言&#x1f4dd; 在项目中导入excel时需要通过下拉框选择值传入&#xff…

解决在Outlook中预定Teams会议不显示入会链接的问题

今天遇到一个很蛋疼的teams问题&#xff0c;花了点时间才解决。本来以为是很简单的问题&#xff0c;随便网上冲浪一下就能找到答案的&#xff0c;结果根本就没有好的解决方案&#xff0c;所以我分享出来希望后来的老哥少走点弯路。 问题描述 简单来说&#xff0c;就是在Outlo…

Pytorch入门—Tensors张量的学习

Tensors张量的学习 张量是一种特殊的数据结构&#xff0c;与数组和矩阵非常相似。在PyTorch中&#xff0c;我们使用张量来编码模型的输入和输出&#xff0c;以及模型的参数。 张量类似于NumPy的ndarrays&#xff0c;只是张量可以在GPU或其他硬件加速器上运行。事实上&#xf…

IntelliJ IDEA 配置JDK

IntelliJ IDEA-之配置JDK 我们的开发神器IDEA安装好了之后&#xff0c;在实际开发中&#xff0c;我们如何去配置好JDK的版本呢&#xff1f; 注意&#xff1a;需要保证JDK在已经成功安装的情况下&#xff0c;再进行IDEA的配置 现在就行动&#xff0c;让IntelliJ IDEA成为你征…

Windows系统使用powershell批量移动特定起始位置的“快捷方式”

移动特定起始位置的“快捷方式” 快捷方式都对应一个的目标和“起始位置”&#xff0c;现在想要把特定起始位置的快捷方式移动到一个文件夹中。 新建文本文档&#xff0c;输入如下内容&#xff1a; # 设置变量 $oldPath "D:\111\111_1" $newPath "D:\111\1…

C语言—操作符详解(操作符、进制转换、原码反码补码、结构体)

1.操作符分类 算术操作符&#xff1a; 、- 、 * 、 / 、%移位操作符&#xff1a;<< >> //移动的是二进制位位操作符&#xff1a;& | ^ //使用二进制位进行计算赋值操作符&#…

前端js面试题--从字符串中删除删除注释代码

问题&#xff1a;从字符串中删除删除注释代码 描述&#xff1a; solution(weex,rex # and react\nflutter\nnative ssss !hybrid app, [#, !]) 写一个solution函数清除后面参数数组里面的字符串 打印效果 代码1 思路&#xff1a; 将字符全凡是有去掉标志符号的全部添加\n…

Ubuntu20.4中复现Graspness

Ubuntu20.4中复现Graspness 文章目录 Ubuntu20.4中复现Graspness1.安装cuda和cudnn2.安装pytorch3.安装MinkowskiEngine4.编译graspnetAPI5. RuntimeError: "floor" "_vml_cpu" not implemented for IntRefernece &#x1f680;非常重要的环境配置&#x1…

pyqt 分组框控件QGroupBox

pyqt 分组框控件QGroupBox 分组框控件QGroupBox介绍效果代码 分组框控件QGroupBox介绍 QGroupBox提供了一个框架&#xff0c;用于将其他控件&#xff08;如按钮、滑块、标签等&#xff09;组合在一起。 QGroupBox 通常包含一个标题栏和一个内容区域。标题栏显示文本标签&#…

经典回溯算法之N皇后问题

问题描述&#xff1a; 有一个N*N的棋盘&#xff0c;需要将N个皇后放在棋盘上&#xff0c;保证棋盘的每一行每一列每一左斜列每一右斜列都最多只能有一个皇后。 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如…

关于模型参数融合的思考

模型参数融合通常指的是在训练过程中或训练完成后将不同模型的参数以某种方式结合起来&#xff0c;以期望得到更好的性能。这种融合可以在不同的层面上进行&#xff0c;例如在神经网络的不同层之间&#xff0c;或者是在完全不同的模型之间。模型参数融合的目的是结合不同模型的…

探索智慧生活:百度Comate引领人工智能助手新潮流

文章目录 百度Comate介绍1. 什么是百度Comate&#xff1f;主要特点 2. Comate的核心功能智能问答功能语音识别功能语音助手功能个性化服务 使用教程(以vscode为例)1. 下载和安装Comate2. 插件配置方式1&#xff1a;无License用户方式2&#xff1a;购买License用户 3. 常用操作快…

软件设计师

软件设计师 第一章 计算机系统基础原/反/补/移码例题&#xff1a; 浮点数例题 海明校验码例题 CISC和RISC*流水线例题 存储系统cache*主存编址计算例题&#xff1a; 可靠性例题 性能指标例题 第二章 操作系统进程例题 PV操作 信号量例题 前驱图例题 死锁计算例题 段页式存储例题…

阵痛中的乳业产业,何时才能成为下一个啤酒产业?

说起饮品&#xff0c;近年来中国啤酒业中各大品牌齐齐聚焦高端化的趋势绝对值得一提。然而&#xff0c;与之相反&#xff0c;国内乳业却是仍未进入高端化阶段&#xff0c;甚至陷入了周期底部中。 图源&#xff1a;中国圣牧财报 增收降利 牧企承受巨大的供需缺口压力 从产业链…

设计模式(2)创造型设计模式

创建型模式 创建型模式1.工厂模式1.1 抽象工厂模式&#xff08;Abstract factory&#xff09;1.2 工厂方法模式&#xff08;Factory Method&#xff09;1.3 简单工厂模式&#xff08;Simple Factory&#xff09; 2. 建造者模式&#xff08;Builder&#xff09;3. 原型模式&…

P8799 [蓝桥杯 2022 国 B] 齿轮

P8799 [蓝桥杯 2022 国 B] 齿轮 分析 最右边的齿轮的转速是最左边齿轮的q倍 最右边的齿轮的半径是最左边齿轮的q倍 题意即为&#xff1a;查询数组中是否存在两个数&#xff0c;其中一个是另一个的q倍 题目范围&#xff1a;查询次数q:2*10^5&#xff0c;数组范围2*10^5&…

2024付费进群系统,源码及搭建变现视频课程(教程+源码)

前三节讲解搭建支付对接&#xff0c;后两节讲解一些引流变现的方法&#xff0c;还有一种变现就是帮人搭建这样的平台&#xff0c;因为全网都没有一套完整的视频教怎么搭建的&#xff0c;有也只是文字教程&#xff0c;一般新人根本看不懂&#xff0c;我视频实操演示&#xff0c;…

学习经验分享【36】论文投稿写作(非理工科文章)

业务进一步扩展&#xff0c;可辅导非理工科偏文科性质的论文辅导&#xff0c;有需要评职称但没有时间精力研究的或者其他相关需求的朋友可咨询了解。 人工智能技术在各领域的发展和思考&#xff0c;类似这种主题的文章。

压缩和归档库-LZ4介绍

1.简介 LZ4是一种快速的压缩算法&#xff0c;提供压缩和解压缩的速度&#xff0c;而牺牲了压缩率。它被设计用于快速的数据压缩和解压缩&#xff0c;特别是用于数据存储和传输。LZ4通常用于需要高速数据处理的场景&#xff0c;如数据库、日志文件处理和实时数据传输。 LZ4的特…
最新文章