当前位置: 首页 > news >正文

(二)详解观察者模式

一.使用场景

当我们需要一个类,在他的内部元素发生变化的时候可以主动通知其他类的时候,同时要保持良好的可拓展性,可以采用观察者模式。

二.核心

观察者模式=出版者+订阅者

我们拥有一个主题对象,和一些其他对象,包括注册成观察者的类和没有注册成观察者的类。当主题对象内部的元素发生改变,主题对象会通知所有注册成观测者的类。同时任何类可以随时注册成观测者或注销自己的观测者身份。

观测模式定义对象之间的一对多依赖,这样一来当一个对象改变时他的所有依赖着都会受到通知并自动更新。

观测者模式应该做到松耦合,主题唯一知道的事情是,观察者提供了观察者接口。我们可以随时添加新的观测者。同时在添加新的观测者的时候不需要修改主题,可以彼此独立的复用主题或观察者。改变主题或观察者其中一方不会影响另一方

三.例子

假设我们需要一款检测气象的类,在观察到气象数据发生变化后,主动向用户展示当前气象状态。

首先我们需要一个观测者类,任何对象都只要继承了观测者类并实现了更新方法都可以当作当作者来实现。

namespace weather {class Observer {public:virtual ~Observer() = default;virtual void update(float temp, float humidity, float pressure) = 0;    //提供一个虚接口让想成为观测者的对象自己实现更新行为};
}

我们还需要一个主题接口,用来给所有观测者提供更新的业务逻辑。这个主题需要具有接受新注册观测者和溢出观测者的能力,还有具有通知所有观测者信息发生改变的能力。

namespace weather {class Observer; // 前置声明class Subject {public:virtual ~Subject() = default;virtual void registerObserver(Observer* o) = 0;    //接受新注册的观测者virtual void removeObserver(Observer* o) = 0;       //注销当前任意观测者virtual void notifyObservers() = 0;        //通知所有观测者信息已发生改变};
}

为了方便观察我们还可以给所欲需要显示元素创建一个接口,当需要显示的时候,实现这个接口,并直接调用他即可

namespace weather {class DisplayElement {public:virtual ~DisplayElement() = default;virtual void display() const = 0;    //给需要实现显示的类提供接口};
}

 实现完了所有所需接口,我们可以针对应用逻辑设计当前所需要的类了。这对目前要求我们需要一个能主动通知观察者的气象类,我们可以让他作为一个主题类。并管理所有当前观测者,在天气发生变化的时候,调用所有观测者的更新函数进行更新。

namespace weather {class WeatherData : public Subject {public:WeatherData() = default;virtual ~WeatherData() = default;void registerObserver(Observer* o)     //注册观测者{observers.push_back(o);}virtual void removeObserver(Observer* o) //删除观测者{for(auto beg = observers.begin(); beg < observers.end(); beg++){if(*beg == o){beg = observers.erase(beg);}}}virtual void notifyObservers()   //通知所有观测者信息发生改变{for (auto observer : observers) //遍历所有的观测者{observer->update(temperature, humidity, pressure);    //调用所有观测者自己提供的更新函数}}void measurementsChanged()    //当气象信息发生改变时,会调用这个函数。给下一层提供,由下 一层调用。{notifyObservers();        //通知所有观测者} void setMeasurements(float temperature, float humidity, float pressure);    //设置天气值,便于调试{temperature = temp;humidity = h;pressure = p;measurementsChanged();}private:std::vector<Observer*> observers;   //管理所有观测者float temperature;  //当前天气的的信息float humidity;float pressure;};
}

接下来我们可以创建一个观测者对象用于在天气温度变化时打印出来当前值。观测者对象可以无限拓展。

namespace weather {class StatisticsDisplay : public Observer, public DisplayElement {private:float maxTemp = 0.0f;float minTemp = 200;float tempSum= 0.0f;int numReadings;Subject& weatherData;public:explicit StatisticsDisplay(Subject& inWeatherData)    //通过构造函数把它注册为观察者: maxTemp(0.0f), minTemp(200), tempSum(0.0f), numReadings(0), weatherData(weatherData){weatherData.registerObserver(this);    }~StatisticsDisplay(){weatherData.removeObserver(this);    //将当前类从观察者中移除}void update(float temperature, float humidity, float pressure)    //获取到更新后的值后和当前值进行对比{tempSum += temp;numReadings++;if (temp > maxTemp) {maxTemp = temp;}if (temp < minTemp) {minTemp = temp;}display();    //打印显示}void display() const //提供自己的打印方法{std::cout << "Avg/Max/Min temperature = " << (tempSum / numReadings)<< "/" << maxTemp << "/" << minTemp << std::endl;}};
}

我们可以根据这样的模板根据需求提供不同的的观察者。

四.优化

按照上面的逻辑去写,每次发生任意一个元素的改变,都会推送给所有的观测者。不论这个观测者需不需要这些数据。我们可以让观测者根据需求从主题类里拉取需要的元素。我们可以在主题类调用观察者类的update函数的时候不传任何参数。然后我们修改主题类,在内部提供get函数用于获取自己的参数。最后我们在update函数被调用的时候通过调用get函数,去向主题类索取自己需要的元素。

总而言之,就是指让观测者知道值已经发生改变。让观测者自己去要具体哪个值。

相关文章:

(二)详解观察者模式

一.使用场景 当我们需要一个类&#xff0c;在他的内部元素发生变化的时候可以主动通知其他类的时候&#xff0c;同时要保持良好的可拓展性&#xff0c;可以采用观察者模式。 二.核心 观察者模式出版者订阅者 我们拥有一个主题对象&#xff0c;和一些其他对象&#xff0c;包…...

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石④

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石④ 第十九章 驱动程序基石④19.7 工作队列19.7.1 内核函数19.7.1.1 定义 work19.7.1.2 使用 work&#xff1a;schedule_work19.7.1.3 其他函数 19.7.2 编程、上机19.7.3 内部机制19.7.3.1 Linux 2.x的工作队列创建过程19.7.3…...

2023 彩虹全新 SUP 模板,卡卡云模板修复版

2023 彩虹全新 SUP 模板&#xff0c;卡卡云模板&#xff0c;首页美化&#xff0c;登陆页美化&#xff0c;修复了 PC 端购物车页面显示不正常的问题。 使用教程 将这俩个数据库文件导入数据库&#xff1b; 其他的直接导入网站根目录覆盖就好&#xff1b; 若首页显示不正常&a…...

【AI视野·今日NLP 自然语言处理论文速览 第四十一期】Tue, 26 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Tue, 26 Sep 2023 Totally 75 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Physics of Language Models: Part 3.1, Knowledge Storage and Extraction Authors Zeyuan Allen Zhu, Yuanz…...

【iptables 实战】05 iptables设置网络转发实验

一、网络架构 实验效果&#xff0c;通过机器B的转发功能&#xff0c;将机器A的报文转发到机器C 本实验准备三台机器分别配置如下网络 机器A ip:192.168.56.104 机器C ip:10.1.0.10 机器B 两张网卡&#xff0c;分别的ip是192.168.56.106和10.1.0.11 如图所示 如下图所示 二、…...

pygame - 贪吃蛇小游戏

蛇每吃掉一个身体块&#xff0c;蛇身就增加一个长度。为了统一计算&#xff0c;界面的尺寸和游戏元素的位置都是身体块长度的倍数 1. 上下左右方向键&#xff08;或者ASDW键&#xff09;控制蛇的移动方向 2. 空格键暂停和继续蛇的身体图片文件&#xff0c;复制到项目的asset\im…...

基于 QT 实现 Task Timer,高效利用时间

一、开发环境 Ubuntu 20.04 QT6.0 二、新建 Qt Wigets Application 这里的基类选择 Wigets&#xff0c; pro 配置文件添加 sql 模块&#xff0c;需要用到 sqlite&#xff0c; QT sql 三、添加数据库连接头文件 // connection.h #ifndef CONNECTION_H #define CONNECTION_…...

图像处理与计算机视觉--第五章-图像分割-霍夫变换

文章目录 1.霍夫变换(Hough Transform)原理介绍2.霍夫变换(Hough Transform)算法流程3.霍夫变换(Hough Transform)算法代码4.霍夫变换(Hough Transform)算法效果 1.霍夫变换(Hough Transform)原理介绍 Hough Transform是一种常用的计算机视觉图形检验方法&#xff0c;霍夫变换一…...

linux下文件操作命令

title: linux下文件操作命令 createTime: 2020-10-29 18:05:52 updateTime: 2020-10-29 18:05:52 categories: linux tags: Linux下文件操作命令 tar命令 使用tar命令一般打包分为两种*.tar ,*.tar.gz 相信大家也使用过tar -zcvf test.tar test/tar -zcvf test.tar.gz test/…...

Golang语法、技巧和窍门

Golang简介 命令式语言静态类型语法标记类似于C&#xff08;但括号较少且没有分号&#xff09;&#xff0c;结构类似Oberon-2编译为本机代码&#xff08;没有JVM&#xff09;没有类&#xff0c;但有带有方法的结构接口没有实现继承。不过有type嵌入。函数是一等公民函数可以返…...

Grander因果检验(格兰杰)原理+操作+解释

笔记来源&#xff1a; 1.【传送门】 2.【传送门】 前沿原理介绍 Grander因果检验是一种分析时间序列数据因果关系的方法。 基本思想在于&#xff0c;在控制Y的滞后项 (过去值) 的情况下&#xff0c;如果X的滞后项仍然有助于解释Y的当期值的变动&#xff0c;则认为 X对 Y产生…...

Python-Flask:编写自动化连接demo脚本:v1.0.0

主函数&#xff1a; # _*_ Coding : UTF-8 _*_ # Time : 13:14 # Author : YYZ # File : Flask # Project : Python_Project_爬虫 import jsonfrom flask import Flask,request,jsonify import sshapi Flask(__name__)# methods: 指定请求方式 接口解析参数host host_info[…...

kafka客户端应用参数详解

一、基本客户端收发消息 Kafka提供了非常简单的客户端API。只需要引入一个Maven依赖即可&#xff1a; <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka_2.13</artifactId><version>3.4.0</version></depend…...

Apache Doris 行列转换可以这样玩

行列转换在做报表分析时还是经常会遇到的&#xff0c;今天就说一下如何实现行列转换吧。 行列转换就是如下图所示两种展示形式的互相转换 1. 行转列 我们来看一个简单的例子&#xff0c;我们要把下面这个表的数据&#xff0c;转换成图二的样式 image-20230914151818953.png …...

【Qt图形视图框架】自定义QGraphicsItem和QGraphicsView,实现鼠标(移动、缩放)及键盘事件、右键事件

自定义QGraphicsItem和QGraphicsView 说明示例myitem.hmyitem.cppmyview.hmyview.cpp调用main.cpp 效果 说明 在使用Qt的图形视图框架实现功能时&#xff0c;一般会在其基础上进行自定义功能实现。 如&#xff1a;滚轮对场景的缩放&#xff0c;鼠标拖动场景中的项&#xff0c;…...

C语言结构体指针学习

结构体变量存放内存中&#xff0c;也有起始地址&#xff0c;定义一个变量来存放这个地址&#xff0c;那这个变量就是结构体指针&#xff1b; typedef struct mydata{int a1;int a2;int a3; }mydata;void CJgtzzView::OnDraw(CDC* pDC) {CJgtzzDoc* pDoc GetDocument();ASSERT…...

华为云云耀云服务器L实例评测|部署在线轻量级备忘录 memos

华为云云耀云服务器L实例评测&#xff5c;部署在线轻量级备忘录 memos 一、云耀云服务器L实例介绍1.1 云服务器介绍1.2 产品优势1.3 应用场景1.4 支持镜像 二、云耀云服务器L实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置 三、部署 memos3.1 memos介绍3.2 Docker 环境搭建…...

详解Avast Driver Updater:电脑驱动更新工具的利器还是多余的软件?

亲爱的读者朋友们&#xff0c;你是不是经常为电脑的驱动问题而烦恼&#xff1f;如果是的话&#xff0c;你可能会对这款软件——Avast Driver Updater 电脑驱动更新工具感兴趣。但在你决定尝试之前&#xff0c;不妨先和我一起深入探讨一下它的优点、缺点以及它适用的使用场景。 …...

大数据Flink(九十五):DML:Window TopN

文章目录 DML:Window TopN DML:Window TopN Window TopN 定义(支持 Streaming):Window TopN 是一种特殊的 TopN,它的返回结果是每一个窗口内的 N 个最小值或者最大值。 应用场景...

使用OKHttpClient访问网络

使用OKHttpClient前要引入依赖&#xff1a; 在build.gradle(Moduel :app)中添加 implementation com.squareup.okhttp3:okhttp:3.14.1 implementation com.squareup.okhttp3:logging-interceptor:3.14.1 implementation com.squareup.okio:okio:1.6.0 1. GET&#xff08;同步…...

maui 开发AMD CPU踩的坑。

刚换的 amd R7735HS 笔记本&#xff0c;8核16线程&#xff0c;32GB内存。性能得实强悍 。 当需要发布iOS版本时发现&#xff0c;我没有macos &#xff0c;那就安装个vmware 吧。看了一下Apple 要求以后的发布的APP需要以xcode14.3或以后版本开发的版本&#xff0c;但xcode14.3…...

宝塔反代openai官方API接口详细教程,502 Bad Gateway问题解决

一、前言 宝塔反代openai官方API接口详细教程&#xff0c;实现国内使用ChatGPT502 Bad Gateway问题解决&#xff0c; 此方法最简单快捷&#xff0c;没有复杂步骤&#xff0c;不容易出错&#xff0c;即最简单&#xff0c;零代码、零部署的方法。 二、实现前提 一台海外VPS服务…...

【leetocde】128. 最长连续序列

给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1&#xff1a; 输入&#xff1a;nums [100,4,200,1,3,2] 输出&#xff1a;4 …...

【Vue3】动态 class 类

如果你想在 Vue.js 中动态设置元素的 class 类名&#xff0c;你可以使用以下两种主要方式&#xff1a; 绑定一个动态的 class 对象&#xff1a;你可以使用 v-bind 或简写的 : 来绑定一个包含类名的对象&#xff0c;其中类名的键是类名字符串&#xff0c;值是一个布尔值或计算属…...

【Redis】redis基本数据类型详解(String、List、Hash、Set、ZSet)

目录 RedisString(字符串)List(列表)Hash(字典)Set(集合)ZSet(有序集合) Redis Redis有5种基本的数据结构&#xff0c;分别为&#xff1a;string&#xff08;字符串&#xff09;、list&#xff08;列表&#xff09;、set&#xff08;集合&#xff09;、hash&#xff08;哈希&a…...

ubuntu源码安装aria2

github:GitHub - aria2/aria2: aria2 is a lightweight multi-protocol & multi-source, cross platform download utility operated in command-line. It supports HTTP/HTTPS, FTP, SFTP, BitTorrent and Metalink. 发行说明&#xff1a;GitHub - aria2/aria2 at releas…...

【多任务案例:猫狗脸部定位与分类】

【猫狗脸部定位与识别】 1 引言2 损失函数3 The Oxford-IIIT Pet Dataset数据集4 数据预处理4 创建模型输入5 自定义数据集加载方式6 显示一批次数据7 创建定位模型8 模型训练9 绘制损失曲线10 模型保存与预测 1 引言 猫狗脸部定位与识别分为定位和识别&#xff0c;即定位猫狗…...

.Net 锁的介绍

在.NET中,有多种锁机制可用于多线程编程,用来确保线程安全和共享资源的同步。以下是.NET中常见的锁机制: 1. **Monitor(互斥锁):** `Monitor` 是.NET中最基本的锁机制之一。它使用 `lock` 关键字实现,可以确保在同一时刻只有一个线程能够访问被锁定的代码块。`Monitor`…...

Office 2021 小型企业版商用办公软件评测:提升工作效率与协作能力的专业利器

作为一名软件评测人员&#xff0c;我将为您带来一篇关于 Office 2021 小型企业版商用办公软件的评测文章。在这篇评测中&#xff0c;我将从实用性、使用场景、优点和缺点等多个方面对该软件进行客观分析&#xff0c;在专业角度为您揭示它的真正实力和潜力。 一、实用性&#xf…...

Monkey测试

一&#xff1a;测试环境搭建 1&#xff1a;下载android-sdk_r24.4.1-windows 2&#xff1a;下载Java 3&#xff1a;配置环境变量&#xff1a;关于怎么配置环境变量&#xff08;百度一下&#xff1a;monkey环境搭建&#xff0c;&#xff09; 二&#xff1a;monkey测试&#xff1…...

微信如何做商城网站/石家庄网站关键词推广

记录点滴32 2012年12月9日 大学三年级 第一学期14周结束 最近很忙吧&#xff0c;挺好的&#xff0c;不是么。不过有时自己还是有抗拒心理&#xff0c;最近真的是作业泛滥&#xff0c;课程设计充斥着每一天。每一天都想着如何完成作业和课程设计。就这样&#xff0c;逼着自己去学…...

星沙做淘宝店铺网站/做企业推广的公司

DevC作为一款功能强大的C集成开发环境&#xff0c;为用户很好的提供了进行编程学习与工作的环境&#xff0c;小编了解到很多初学用户不知道怎么建立头文件&#xff0c;如果你还不知道具体的操作方法&#xff0c;就赶快来看看下面的教程吧&#xff0c;小编带你快速入门建立头文件…...

网站页面静态化方案/网络事件营销

计算机网络&#xff1a;自顶向下方法第一章&#xff1a;计算机和因特网1、什么是因特网1、因特网具体构成不管是桌面PC、手机、Linux工作站等等&#xff0c;这些所有设备都称为主机或端系统。端系统通过通信链路(communication link)和分组交换机(packet switch)连接到一起&…...

视频网站是如何做的/会员制营销方案

2019独角兽企业重金招聘Python工程师标准>>> 1.ListView滑动方向判断 代码很简单&#xff0c;给mListView监听onScrollListener事件&#xff0c;然后在onScroll进行判断 //listView中第一项的索引private int mListViewFirstItem 0;//listView中第一项的在屏幕中的…...

网站建设新方式简单省时/企业网站优化

C语言中计算二叉树的宽度的两种方式二叉树作为一种很特殊的数据结构&#xff0c;功能上有很大的作用&#xff01;今天就来看看怎么计算一个二叉树的最大的宽度吧。采用递归方式下面是代码内容&#xff1a;int GetMaxWidth(BinaryTree pointer){int width[10];//加入这棵树的最大…...

技术支持 沧州辉煌网络-网站建设/上海百度推广客服电话

MySQL 常规操作 1. 查询 1.1 普通查询 select * from students; -- 获取所有数据 select * from students where age 15; -- 获取年龄为15的数据 select * from students where age 15 and sex male; 1. 2 模糊查询 select * from students where name like %小%; -…...