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

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。主题更新时,所有观察者都会收到通知。

八.总结

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

相关文章:

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

文章目录 一.什么是观察者模式&#xff1f;二.观察者模式的结构三.观察者模式的应用场景四.观察者模式的优缺点五.观察者模式的实现&#xff08;C示例&#xff09;六.观察者模式的实现&#xff08;JAVA示例&#xff09;七.代码解释八.总结 类图&#xff1a; 观察者设计模式类图…...

【CUDA】Branch Divergence and Unrolling Loop

目录 一、避免分支发散 1.1 并行规约问题 1.2 并行规约中的发散 二、UNrolling Loops 一、避免分支发散 控制流有时依赖于 thread 索引。同一个warp中&#xff0c;一个条件分支可能导致性能很差。通过重新组织数据获取模式可以减少或避免 warp divergence。具体问题查看下…...

深度学习:卷积神经网络的计算复杂度,顺序操作,最大路径长度

卷积层的计算复杂度 在深度学习中&#xff0c;卷积层的计算复杂度主要取决于卷积核的大小、输入和输出的通道数量、以及输入序列的长度。具体来说&#xff0c;卷积层的计算复杂度可以通过以下几个因素来计算&#xff1a; 卷积核大小 k&#xff1a;卷积核的大小决定了每次卷积操…...

springboot 配置文件中 multipart.max-file-size 各个版本的写法

由于springboot具有几个版本&#xff0c;不同版本对于文件上传最大限制的配置也有所不同。 所以要注意springboot本身的版本&#xff0c;不然会一直报错 在springboot1.3版本中&#xff1a; multipart.maxFileSize在springboot1.4与springboot1.5版本中&#xff1a; spring…...

linux 中mysql查看慢日志

1、到mysql容器&#xff0c;先登录到数据库&#xff0c;查看是否开启 mysql -h 127.0.0.1 -uroot -p SHOW VARIABLES LIKE slow_query_log; 2、如果没有开启&#xff0c;需要先开启 set global slow_query_log ON; 3、查看慢日志文件 SHOW VARIABLES LIKE slow_query_log…...

单片机的基本组成与工作原理

单片机&#xff08;Microcontroller Unit, MCU&#xff09;是一种将计算机的主要部分集成在一个芯片上的小型计算机系统。它通常包括中央处理器&#xff08;CPU&#xff09;、存储器&#xff08;Memory&#xff09;、输入输出接口&#xff08;I/O Ports&#xff09;、定时器/计…...

智慧隧道和智慧交通

通过引入先进的物联网技术&#xff0c;将各种硬件设备如传感器、摄像头、控制系统等有效地连接并管理起来&#xff0c;以实现道路安全和交通流畅的目标。这些设备将能够实时监控和控制隧道内的各种设备和系统&#xff0c;从而提高道路安全、提升驾驶体验并降低管理成本。 在这个…...

List、Set、Map详解和区别

在 Java 中&#xff0c;List、Set、Map是常用的集合类型&#xff0c;它们各自具有不同的特点和用途&#xff0c;以下是对它们的详细介绍及区别分析&#xff1a; List&#xff08;列表&#xff09; 特点&#xff1a; 有序性&#xff1a;List中的元素是有序的&#xff0c;即元素…...

界面控件DevExpress WinForms v24.2新功能预览 - 支持.NET 9

DevExpress WinForms 拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…...

Postman之pm.test断言操作

Postman之pm.test断言操作 1.断言方法2.连接符3.条件判断符 用于验证请求的响应数据是否符合预期 1.断言方法 pm.test()&#xff1a;定义一个测试函数&#xff0c;接受两个参数&#xff0c;一个字符串参数用来描述该测试&#xff0c;一个返回True/False的函数 语法格式&#…...

对数几率回归

对数几率回归简介 对数几率回归&#xff08;Logistic Regression&#xff09;是一种用于解决分类问题的经典统计模型&#xff0c;其核心思想是利用逻辑函数&#xff08;Sigmoid函数&#xff09;将线性回归模型的输出值映射到概率范围 [0, 1]&#xff0c;从而实现分类预测。对数…...

docker 配置同宿主机共同网段的IP 同时通过通网段的另一个电脑实现远程连接docker

docker配置网络 #宿主机执行命令 ifconfig 查询对应的主机ip 子网掩码 网关地址 #[网卡名称]&#xff1a;inet[主机IP] netmask[子网掩码] broadcast[网关地址]这里需要重点关注&#xff1a;eno1[网卡名称]以及【192.168.31.225】网关地址 在宿主机执行docker命令创建一个虚拟…...

4-7-1.C# 数据容器 - LinkedList(LinkedList 的定义、LinkedList 结点的遍历、LinkedList 的常用方法)

LinkedList 概述 LinkedList<T> 通过节点&#xff08;Node&#xff09;来存储数据&#xff0c;每个节点包含数据和指向下一个节点的引用 LinkedList<T> 存储的元素是可重复的 LinkedList<T> 支持泛型&#xff0c;可以指定存储的元素的类型 LinkedList<…...

「三」体验HarmonyOS端云一体化开发模板——使用DevEco Studio直接创建端云一体化工程

关于作者 白晓明 宁夏图尔科技有限公司董事长兼CEO、坚果派联合创始人 华为HDE、润和软件HiHope社区专家、鸿蒙KOL、仓颉KOL 华为开发者学堂/51CTO学堂/CSDN学堂认证讲师 开放原子开源基金会2023开源贡献之星 「目录」 「一」HarmonyOS端云一体化概要 「二」体验HarmonyOS端云一…...

确保以管理员权限运行 Visual Studio 开发者命令提示符

文章目录 解决方法&#xff1a;1. 以管理员身份运行命令提示符2. 改变目录权限3. 改变项目目录位置4. 检查文件系统权限 总结&#xff1a; ********************************************************************** ** Visual Studio 2022 Developer Command Prompt v17.12.0 …...

命令执行简单(棱角社区有毒)

前言&#xff1a;小迪安全2022第一节反弹shell&#xff0c;小迪用的是两台都是云服务器&#xff0c;没有服务器可以在自己的主机上搭建也是可以的&#xff0c;主机上搭两个网站 思路&#xff1a;生成一个木马文件&#xff0c;下载到本机&#xff0c;然后利用本机上传到目标主机…...

Keil基于ARM Compiler 5的工程迁移为ARM Compiler 6的工程

环境&#xff1a; keil版本为5.38&#xff0c;版本务必高于5.30 STM32F4的pack包版本要高于2.9 软件包下载地址&#xff1a;https://zhuanlan.zhihu.com/p/262507061 一、更改Keil中编译器 更改后编译&#xff0c;会报很多错&#xff0c;先不管。 二、更改头文件依赖 观察…...

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成本添加访问级监控

互联网的安全感这个概念源于阿里。顾名思义&#xff0c;让互联网的用户对于web产品能够产生足够的信任和依赖。特别是涉及到用户资金交易的站点&#xff0c;一次严重的用户资料泄露就可以彻底毁掉你的品牌。 然而当前阶段除了bat大部分互联网行业的企业对于网络安全给的重视都…...

【Three.js基础学习】26. Animated galaxy

前言 shaders实现星系 课程回顾 使用顶点着色器为每个粒子设置动画 a属性 &#xff0c; u制服 &#xff0c;v变化 像素比&#xff1a;window.devicePixelRatio 自动从渲染器检索像素比 renderer.getPixelRatio() 如何尺寸衰减&#xff0c; 放大缩小视角时&#xff0c;粒子都是同…...

vscode使用ssh配置docker容器环境

1 创建容器&#xff0c;并映射主机和容器的指定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 论文信息&#xff1a; 简介: 本文讨论的背景是大型语言模型&#xff08;LLMs&#xff09;的自我对齐问题。传统的LLMs对齐方法依赖于昂贵的训练和人类偏好注释&am…...

【LeetCode】167. 两数之和 II - 输入有序数组

描述 给定一个下标从 1 开始的整数数组numbers&#xff0c;该数组已按非递减顺序排列&#xff0c;请从数组中找出满足相加之和等于目标数target的两个数。如果这两个数分别是numbers[index1]和numbers[index2]&#xff0c;返回整数数组[index1, index2]。 只存在唯一答案&#…...

Getx:GetxController依赖管理02,Binding绑定全局控制器(懒加载Controller)

在使用GetX 状态管理器的时候&#xff0c;如果每个页面都手动实例化一个控制器就太麻烦了&#xff0c; Binding 的作用就是所有需要进行状态管理的控制器进行统一初始化 创建全局控制器Binding import package:get/get.dart; import ../controllers/counter.dart; // 同上一篇内…...

leetcode 找不同

389. 找不同 已解答 简单 相关标签 相关企业 给定两个字符串 s 和 t &#xff0c;它们只包含小写字母。 字符串 t 由字符串 s 随机重排&#xff0c;然后在随机位置添加一个字母。 请找出在 t 中被添加的字母。 示例 1&#xff1a; 输入&#xff1a;s "abcd"…...

2025 - 生信信息学 - GEO数据分析 - RF分析(随机森林)

GEO数据分析 - RF分析&#xff08;随机森林&#xff09; 01 准备数据文件 #install.packages("randomForest")#引用包 library(randomForest) set.seed(123456)inputFile"diffGeneExp.txt" #输入文件 setwd("/Users/wangyang/Desktop/BCBM/02ra…...

Matlab深度学习(四)——AlexNet卷积神经网络

网络搭建参考&#xff1a;手撕 CNN 经典网络之 AlexNet&#xff08;理论篇&#xff09;-CSDN博客 在实际工程应用中&#xff0c;构建并训练一个大规模的卷积神经网络是比较复杂的&#xff0c;需要大量的数据以及高性能的硬件。如果通过训练好的典型网络稍加改进&#xf…...

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…...

数据治理、数据素养和数据质量管理:文献综述

注意&#xff1a;这并不是正式发表的论文&#xff0c;只是一篇用来交作业的文章 摘要 随着数据时代的到来&#xff0c;数据治理、数据素养和数据质量管理成为组织数据管理中的三大核心概念。本文基于相关研究与实践&#xff0c;对这三个领域进行全面综述&#xff0c;探讨它…...

网站建设视频教程。/短视频拍摄剪辑培训班

money_text (EditText) findViewById(R.id.money_text);// 代码中实现点击回车键&#xff0c;完成输入软键盘消失&#xff0c;也可以在布局中实现了money_text.setOnKeyListener(new OnKeyListener() {Overridepublic boolean onKey(View v, int keyCode, KeyEvent event) {if…...

网站做分站/网络推广理实一体化软件

在某些情况下为了实现Windows多台服务器负载均衡&#xff0c;需要使用共享来做图片及附件的上传空间。 这个时候就需要使用到Samba、IIS虚拟目录等相关技术 Web服务器使用upload作为上传的目录&#xff0c;现在需要使用2台服务器做负载均衡&#xff0c;后台使用一台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*$/, ); } 看起来不怎么样&#xff0c; 动用了两…...

做网站后要回源码有何用/厦门百度开户

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 东南大学 …...

秦皇岛网站建设价格/百度站长工具抓取诊断

对于很多玩抖音的作者来说&#xff0c;瓶颈期就在于你创作的内容&#xff0c;没人看&#xff0c;粉丝只有那么几个几十个&#xff0c;怎么涨都涨不上去。 下面&#xff0c;我会给大家提供几个涨粉的思路&#xff0c;在内容为王道的自媒体时代&#xff0c;最重要和最核心的当然…...