23种设计模式-观察者(Observer)设计模式
文章目录
- 一.什么是观察者模式?
- 二.观察者模式的结构
- 三.观察者模式的应用场景
- 四.观察者模式的优缺点
- 五.观察者模式的实现(C++示例)
- 六.观察者模式的实现(JAVA示例)
- 七.代码解释
- 八.总结
类图: 观察者设计模式类图
一.什么是观察者模式?
观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象之间的一对多关系。即一个对象(称为“主题”)状态发生改变时,会自动通知依赖它的其他对象(称为“观察者”)。这种模式在很多场景中都非常适用,比如发布-订阅系统、事件监听、界面刷新等。
观察者模式的特点是松耦合:观察者和主题不需要彼此了解细节,只需按照约定进行交互,这种设计提升了代码的可维护性和可扩展性。
二.观察者模式的结构
- Subject(主题):又称被观察者,用于存储和管理观察者,并在自身状态变化时通知观察者。
- Observer(观察者):观察者接口,用于定义更新方法,所有观察者实现该接口。
- ConcreteSubject(具体主题):继承自主题接口,实现状态管理和通知观察者的具体逻辑。
- ConcreteObserver(具体观察者):实现观察者接口,通过获取主题更新,执行相应的行为。
三.观察者模式的应用场景
- 事件监听:用户在UI界面点击按钮时,按钮组件通过通知事件监听器实现某种交互。
- 数据变化通知:在数据变化时,多个视图自动更新显示。例如,股票价格变化时,订阅者自动更新价格显示。
- 发布-订阅系统:发布者更新数据时,通知订阅的所有观察者,实现自动信息推送。
四.观察者模式的优缺点
-
优点:
- 解耦:主题与观察者之间的耦合度较低,可以独立扩展。
- 自动通知:当主题状态发生变化时,无需手动通知每个观察者。
-
缺点:
- 通知耗时:当观察者数量较多或更新频繁时,可能会导致性能问题。
- 顺序依赖:如果通知是同步进行的,通知的顺序会影响整个流程。
五.观察者模式的实现(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);}
}
七.代码解释
- Observer 接口:Observer是一个抽象基类,包含update方法,所有观察者都要实现该方法,以响应主题的通知。
- Subject 接口:Subject也是一个抽象基类,提供addObserver、removeObserver和notifyObservers方法,主题通过这些方法管理和通知观察者。
- ConcreteSubject 类:这是主题的具体实现类,包含observers向量用于保存观察者。当主题状态改变时,通过调用notifyObservers通知所有观察者。
- ConcreteObserver 类:这是观察者的具体实现类。每个观察者都有一个name属性,并在update方法中响应通知。
- 测试代码:在main函数中创建了一个主题对象subject,并注册两个观察者对象observer1和observer2。主题更新时,所有观察者都会收到通知。
八.总结
观察者模式是一种非常实用的设计模式,特别是在需要通知多个对象的场景中非常合适。它让主题和观察者之间实现了低耦合,从而增强系统的灵活性和扩展性。通过实现一个通用的观察者接口和主题接口,观察者模式能够很好地应对需求的变化,使得观察者可以随时添加、删除,并根据主题的状态变化而自动更新,从而达到良好的解耦效果。
相关文章:
23种设计模式-观察者(Observer)设计模式
文章目录 一.什么是观察者模式?二.观察者模式的结构三.观察者模式的应用场景四.观察者模式的优缺点五.观察者模式的实现(C示例)六.观察者模式的实现(JAVA示例)七.代码解释八.总结 类图: 观察者设计模式类图…...
【CUDA】Branch Divergence and Unrolling Loop
目录 一、避免分支发散 1.1 并行规约问题 1.2 并行规约中的发散 二、UNrolling Loops 一、避免分支发散 控制流有时依赖于 thread 索引。同一个warp中,一个条件分支可能导致性能很差。通过重新组织数据获取模式可以减少或避免 warp divergence。具体问题查看下…...
深度学习:卷积神经网络的计算复杂度,顺序操作,最大路径长度
卷积层的计算复杂度 在深度学习中,卷积层的计算复杂度主要取决于卷积核的大小、输入和输出的通道数量、以及输入序列的长度。具体来说,卷积层的计算复杂度可以通过以下几个因素来计算: 卷积核大小 k:卷积核的大小决定了每次卷积操…...
springboot 配置文件中 multipart.max-file-size 各个版本的写法
由于springboot具有几个版本,不同版本对于文件上传最大限制的配置也有所不同。 所以要注意springboot本身的版本,不然会一直报错 在springboot1.3版本中: multipart.maxFileSize在springboot1.4与springboot1.5版本中: spring…...
linux 中mysql查看慢日志
1、到mysql容器,先登录到数据库,查看是否开启 mysql -h 127.0.0.1 -uroot -p SHOW VARIABLES LIKE slow_query_log; 2、如果没有开启,需要先开启 set global slow_query_log ON; 3、查看慢日志文件 SHOW VARIABLES LIKE slow_query_log…...
单片机的基本组成与工作原理
单片机(Microcontroller Unit, MCU)是一种将计算机的主要部分集成在一个芯片上的小型计算机系统。它通常包括中央处理器(CPU)、存储器(Memory)、输入输出接口(I/O Ports)、定时器/计…...
智慧隧道和智慧交通
通过引入先进的物联网技术,将各种硬件设备如传感器、摄像头、控制系统等有效地连接并管理起来,以实现道路安全和交通流畅的目标。这些设备将能够实时监控和控制隧道内的各种设备和系统,从而提高道路安全、提升驾驶体验并降低管理成本。 在这个…...
List、Set、Map详解和区别
在 Java 中,List、Set、Map是常用的集合类型,它们各自具有不同的特点和用途,以下是对它们的详细介绍及区别分析: List(列表) 特点: 有序性:List中的元素是有序的,即元素…...
界面控件DevExpress WinForms v24.2新功能预览 - 支持.NET 9
DevExpress WinForms 拥有180组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜…...
Postman之pm.test断言操作
Postman之pm.test断言操作 1.断言方法2.连接符3.条件判断符 用于验证请求的响应数据是否符合预期 1.断言方法 pm.test():定义一个测试函数,接受两个参数,一个字符串参数用来描述该测试,一个返回True/False的函数 语法格式&#…...
对数几率回归
对数几率回归简介 对数几率回归(Logistic Regression)是一种用于解决分类问题的经典统计模型,其核心思想是利用逻辑函数(Sigmoid函数)将线性回归模型的输出值映射到概率范围 [0, 1],从而实现分类预测。对数…...
docker 配置同宿主机共同网段的IP 同时通过通网段的另一个电脑实现远程连接docker
docker配置网络 #宿主机执行命令 ifconfig 查询对应的主机ip 子网掩码 网关地址 #[网卡名称]:inet[主机IP] netmask[子网掩码] broadcast[网关地址]这里需要重点关注:eno1[网卡名称]以及【192.168.31.225】网关地址 在宿主机执行docker命令创建一个虚拟…...
4-7-1.C# 数据容器 - LinkedList(LinkedList 的定义、LinkedList 结点的遍历、LinkedList 的常用方法)
LinkedList 概述 LinkedList<T> 通过节点(Node)来存储数据,每个节点包含数据和指向下一个节点的引用 LinkedList<T> 存储的元素是可重复的 LinkedList<T> 支持泛型,可以指定存储的元素的类型 LinkedList<…...
「三」体验HarmonyOS端云一体化开发模板——使用DevEco Studio直接创建端云一体化工程
关于作者 白晓明 宁夏图尔科技有限公司董事长兼CEO、坚果派联合创始人 华为HDE、润和软件HiHope社区专家、鸿蒙KOL、仓颉KOL 华为开发者学堂/51CTO学堂/CSDN学堂认证讲师 开放原子开源基金会2023开源贡献之星 「目录」 「一」HarmonyOS端云一体化概要 「二」体验HarmonyOS端云一…...
确保以管理员权限运行 Visual Studio 开发者命令提示符
文章目录 解决方法:1. 以管理员身份运行命令提示符2. 改变目录权限3. 改变项目目录位置4. 检查文件系统权限 总结: ********************************************************************** ** Visual Studio 2022 Developer Command Prompt v17.12.0 …...
命令执行简单(棱角社区有毒)
前言:小迪安全2022第一节反弹shell,小迪用的是两台都是云服务器,没有服务器可以在自己的主机上搭建也是可以的,主机上搭两个网站 思路:生成一个木马文件,下载到本机,然后利用本机上传到目标主机…...
Keil基于ARM Compiler 5的工程迁移为ARM Compiler 6的工程
环境: keil版本为5.38,版本务必高于5.30 STM32F4的pack包版本要高于2.9 软件包下载地址:https://zhuanlan.zhihu.com/p/262507061 一、更改Keil中编译器 更改后编译,会报很多错,先不管。 二、更改头文件依赖 观察…...
Kafka-创建topic源码
一、命令创建topic kafka-topics --create --topic quickstart-events --bootstrap-server cdh1:9092 --partitions 2 --replication-factor 2 二、kafka-topics脚本 exec $(dirname $0)/kafka-run-class.sh org.apache.kafka.tools.TopicCommand "$" 脚本中指定了…...
【网络安全】(一) 0成本添加访问级监控
互联网的安全感这个概念源于阿里。顾名思义,让互联网的用户对于web产品能够产生足够的信任和依赖。特别是涉及到用户资金交易的站点,一次严重的用户资料泄露就可以彻底毁掉你的品牌。 然而当前阶段除了bat大部分互联网行业的企业对于网络安全给的重视都…...
【Three.js基础学习】26. Animated galaxy
前言 shaders实现星系 课程回顾 使用顶点着色器为每个粒子设置动画 a属性 , u制服 ,v变化 像素比:window.devicePixelRatio 自动从渲染器检索像素比 renderer.getPixelRatio() 如何尺寸衰减, 放大缩小视角时,粒子都是同…...
vscode使用ssh配置docker容器环境
1 创建容器,并映射主机和容器的指定ssh服务端口 2 进入容器 docker exec -it <容器ID> /bin/bash 3在容器中安装ssh服务 apt-get update apt-get install openssh-server 接着修改ssh文件信息,将容器的10008端口暴露出来允许root用户使用ssh登录 vim /…...
NLP论文速读(EMNLP 2024)|动态奖励与提示优化来帮助语言模型的进行自我对齐
论文速读|Dynamic Rewarding with Prompt Optimization Enables Tuning-free Self-Alignment of Language Models 论文信息: 简介: 本文讨论的背景是大型语言模型(LLMs)的自我对齐问题。传统的LLMs对齐方法依赖于昂贵的训练和人类偏好注释&am…...
【LeetCode】167. 两数之和 II - 输入有序数组
描述 给定一个下标从 1 开始的整数数组numbers,该数组已按非递减顺序排列,请从数组中找出满足相加之和等于目标数target的两个数。如果这两个数分别是numbers[index1]和numbers[index2],返回整数数组[index1, index2]。 只存在唯一答案&#…...
Getx:GetxController依赖管理02,Binding绑定全局控制器(懒加载Controller)
在使用GetX 状态管理器的时候,如果每个页面都手动实例化一个控制器就太麻烦了, Binding 的作用就是所有需要进行状态管理的控制器进行统一初始化 创建全局控制器Binding import package:get/get.dart; import ../controllers/counter.dart; // 同上一篇内…...
leetcode 找不同
389. 找不同 已解答 简单 相关标签 相关企业 给定两个字符串 s 和 t ,它们只包含小写字母。 字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。 请找出在 t 中被添加的字母。 示例 1: 输入:s "abcd"…...
2025 - 生信信息学 - GEO数据分析 - RF分析(随机森林)
GEO数据分析 - RF分析(随机森林) 01 准备数据文件 #install.packages("randomForest")#引用包 library(randomForest) set.seed(123456)inputFile"diffGeneExp.txt" #输入文件 setwd("/Users/wangyang/Desktop/BCBM/02ra…...
Matlab深度学习(四)——AlexNet卷积神经网络
网络搭建参考:手撕 CNN 经典网络之 AlexNet(理论篇)-CSDN博客 在实际工程应用中,构建并训练一个大规模的卷积神经网络是比较复杂的,需要大量的数据以及高性能的硬件。如果通过训练好的典型网络稍加改进…...
etcd defrag
场景 prometheus监控告警,告警信息如下 etcd cluster "kube-etcd": database size in use on instance xx is 33.45% of the actual allocated disk space, please run defragmentation (e.g. etcdctl defrag) to retrieve the unused fragmented disk space.处理…...
golang语言整合jwt+gin框架实现token
1.下载jwt go get -u github.com/dgrijalva/jwt-go2.新建生成token和解析token文件 2.1 新建common文件夹和jwtConfig文件夹 新建jwtconfig.go文件 2.2 jwtconfig.go文件代码 /* Time : 2021/8/2 下午3:03 Author : mrxuexi File : main Software: GoLand */ package jwtC…...
数据治理、数据素养和数据质量管理:文献综述
注意:这并不是正式发表的论文,只是一篇用来交作业的文章 摘要 随着数据时代的到来,数据治理、数据素养和数据质量管理成为组织数据管理中的三大核心概念。本文基于相关研究与实践,对这三个领域进行全面综述,探讨它…...
网站建设视频教程。/短视频拍摄剪辑培训班
money_text (EditText) findViewById(R.id.money_text);// 代码中实现点击回车键,完成输入软键盘消失,也可以在布局中实现了money_text.setOnKeyListener(new OnKeyListener() {Overridepublic boolean onKey(View v, int keyCode, KeyEvent event) {if…...
网站做分站/网络推广理实一体化软件
在某些情况下为了实现Windows多台服务器负载均衡,需要使用共享来做图片及附件的上传空间。 这个时候就需要使用到Samba、IIS虚拟目录等相关技术 Web服务器使用upload作为上传的目录,现在需要使用2台服务器做负载均衡,后台使用一台Samba服务器…...
上海注册公司代办/网络优化包括
正则表达式——总结JS去掉首尾空格 http://blog.csdn.net/qq_33729889/article/details/55510648 js去除空格的方法目前共有12种: 实现1 String.prototype.trim function() {return this.replace(/^\s\s*/, ).replace(/\s\s*$/, ); } 看起来不怎么样, 动用了两…...
做网站后要回源码有何用/厦门百度开户
Linux 管理员手册(5)--引导和关机(转)本节说明当Linux系统引导和关机时发生了什么,应该任何正确完成. 如果没有遵循正确的过程, 文件可能损坏或丢失. 引导和关机概述 开启计算机并导致其操作系统被加载的过程 叫引导. The name comes from an image of the computer pulling it…...
做网站工作室找客户难/seo教程培训
yum install ntp ntpdate #ntpdate -u cn.pool.ntp.org //写入硬件 #hwclock -w 以下是国内常见的NTP服务器 ntp.sjtu.edu.cn 202.120.2.101 上海交通大学网络中心 s1a.time.edu.cn 北京邮电大学 s1b.time.edu.cn 清华大学 s1c.time.edu.cn 北京大学 s1d.time.edu.cn 东南大学 …...
秦皇岛网站建设价格/百度站长工具抓取诊断
对于很多玩抖音的作者来说,瓶颈期就在于你创作的内容,没人看,粉丝只有那么几个几十个,怎么涨都涨不上去。 下面,我会给大家提供几个涨粉的思路,在内容为王道的自媒体时代,最重要和最核心的当然…...