2023-7-13-第十八式观察者模式

news2024/11/25 22:29:57


🍿*★,°*:.☆( ̄▽ ̄)/$:*.°★* 🍿

💥💥💥欢迎来到🤞汤姆🤞的csdn博文💥💥💥
💟💟喜欢的朋友可以关注一下,下次更新不迷路💟💟
😆😆😆私聊获取个人订阅号哦,欢迎订阅共同学习😆😆😆
💖💖💖💖可以加入大家庭群聊,一起学习天天有福利💖💖💖💖





🍬本文摘要

在这里插入图片描述

设计方法二十三式之观察者模式


目录

  • 🍬本文摘要
  • 😉一、基础概念
  • 🐱‍🐉二、观察者模式实现
  • 🎉三、模块之间的关系
  • 🐱‍🚀四、注意事项
  • 🎂五、使用场景
  • 🍳参考文献
  • 🧊文章总结



😉一、基础概念

观察者模式(Observer Pattern)是一种软件设计模式,用于实现对象间的一对多依赖关系。在该模式中,当一个对象(被观察者或主题)的状态发生变化时,它会自动通知其所有依赖对象(观察者),使得这些观察者能够及时更新自己的状态。

观察者模式涉及以下几个核心角色:

  1. Subject(被观察者/主题):定义了被观察的对象接口。它维护一组观察者对象,并提供添加、删除和通知观察者的方法。

  2. Observer(观察者):定义了接收和处理被观察者通知的接口。观察者通过该接口与被观察者建立联系,并在被观察者状态发生变化时进行相应的更新操作。

  3. ConcreteSubject(具体的被观察者/具体的主题):实现了被观察者接口,并维护了一个观察者列表。它负责管理观察者的注册、移除和通知操作。

  4. ConcreteObserver(具体的观察者):实现了观察者接口,并定义了在接收到被观察者通知时所要执行的操作。每个具体观察者可以有不同的行为。

观察者模式的优点包括:

  • 解耦性:被观察者和观察者之间是松散耦合的,它们可以独立变化而互不影响。
  • 可扩展性:可以方便地增加新的观察者或被观察者,无需修改已有代码。
  • 一致性:观察者将根据被观察者发出的通知实时更新状态,保持与被观察者的一致性。

观察者模式在许多领域中都有广泛应用,例如GUI事件处理、消息队列、发布-订阅机制等。它提供了一种灵活而可扩展的方式来建立对象之间的通信和协作关系。


🐱‍🐉二、观察者模式实现

在C++中实现观察者模式,可以按照以下步骤进行:

  1. 定义Subject(被观察者/主题)接口或基类。它应包含用于注册、注销和通知观察者的方法。例如:
class Subject {
public:
    virtual void attach(Observer* observer) = 0;
    virtual void detach(Observer* observer) = 0;
    virtual void notify() = 0;
};
  1. 定义Observer(观察者)接口或基类。它应包含接收和处理被观察者通知的方法。例如:
class Observer {
public:
    virtual void update() = 0;
};
  1. 实现具体的Subject类,继承自Subject接口或基类。它负责管理观察者列表,实现注册、注销和通知操作。例如:
class ConcreteSubject : public Subject {
private:
    std::vector<Observer*> observers;
public:
    void attach(Observer* observer) override {
        observers.push_back(observer);
    }

    void detach(Observer* observer) override {
        // 在observers中移除observer
    }

    void notify() override {
        for (Observer* observer : observers) {
            observer->update();
        }
    }
};
  1. 实现具体的Observer类,继承自Observer接口或基类。它定义了在接收到被观察者通知时所要执行的操作。例如:
class ConcreteObserver : public Observer {
public:
    void update() override {
        // 执行相应的操作
    }
};
  1. 在主程序中创建具体的被观察者和观察者对象,并建立它们之间的关系。例如:
int main() {
    ConcreteSubject subject;
    ConcreteObserver observer1;
    ConcreteObserver observer2;

    subject.attach(&observer1);
    subject.attach(&observer2);

    // ...

    subject.notify();

    return 0;
}

通过以上步骤,你可以实现一个简单的观察者模式。当被观察者(subject)发生变化时,调用notify方法会通知所有观察者(observers),使它们执行相应的操作(例如update方法)。需要根据具体需求来适配和扩展这个基本框架。


🎉三、模块之间的关系

观察者模式中,模块之间的关系可以被描述为一种一对多的依赖关系。具体来说:

  1. 被观察者(Subject)是一个核心模块,它维护了一个观察者列表,并提供了注册、注销和通知观察者的方法。被观察者通常会在自身状态发生变化时调用通知方法,以便通知所有观察者。

  2. 观察者(Observer)是依赖于被观察者的模块。每个观察者都实现了一个update方法,用于接收和处理被观察者的通知。观察者根据需要进行相应的操作,以保持与被观察者状态的一致性或响应状态的变化。

  3. 被观察者和观察者之间是松散耦合的。被观察者并不直接依赖于特定的观察者,而是通过通用的观察者接口与观察者进行交互。这使得被观察者能够动态地添加、删除和管理观察者,而无需修改被观察者的代码。

  4. 多个观察者可以同时观察同一个被观察者。当被观察者状态发生变化时,它会通知所有已注册的观察者,使得每个观察者都能够及时更新自己的状态。

总结起来,观察者模式通过被观察者和观察者之间的松散耦合关系,实现了一种动态的、可扩展的通信机制。被观察者在状态发生变化时通知观察者,观察者根据需要进行相应的操作。这种模块之间的依赖关系允许系统以灵活的方式处理状态变化,并支持解耦和可重用性。


🐱‍🚀四、注意事项

在使用观察者模式时,有几个注意事项需要考虑:

  1. 被观察者和观察者之间的关系要慎重设计:确保被观察者和观察者之间的关系合理,避免过度依赖或混乱的关联。一个被观察者应该知道它的观察者,并且观察者只与所需的被观察者建立联系。

  2. 避免循环引用:在实现观察者模式时,要小心处理观察者和被观察者之间的引用关系,以避免形成循环引用。如果存在循环引用,可能导致内存泄漏或其他意外行为。

  3. 观察者的更新顺序:观察者模式中,观察者的更新顺序是不确定的。如果观察者之间存在相互依赖关系,可能会影响到系统的行为。因此,要谨慎处理观察者的更新顺序,确保系统能够正确运行。

  4. 考虑线程安全性:如果在多线程环境中使用观察者模式,需要考虑线程安全性。确保对共享数据的访问和修改是线程安全的,可以通过使用互斥锁或其他线程同步机制来实现。

  5. 避免频繁的通知:被观察者应该避免频繁地通知观察者,以减少不必要的开销。可以根据具体情况,采用合适的策略进行通知,例如延迟通知、批量通知等。

  6. 考虑性能问题:在设计观察者模式时,需要注意性能问题。如果观察者数量庞大或通知频率很高,可能会对系统的性能产生影响。在这种情况下,可以考虑优化通知机制或采用其他设计模式。

总之,观察者模式是一种强大而灵活的模式,但在使用它时需要谨慎考虑上述注意事项,以确保系统的稳定性、可维护性和性能。


🎂五、使用场景

观察者模式适用于以下情况:

  1. 当一个对象的状态变化需要通知其他多个对象,并且这些对象的更新操作可能会根据被观察者的状态变化而改变时,可以使用观察者模式。例如,当一个图形界面中的按钮被点击时,需要通知多个视图组件进行相应的更新。

  2. 当一个对象拥有两个或更多的关注点,并且希望将这些关注点分离开来,使得每个关注点都可以独立地变化和扩展时,可以使用观察者模式。通过观察者模式,可以将不同的关注点分别实现为观察者,从而提高系统的可维护性和可扩展性。

  3. 当需要在不同层级的模块之间建立松耦合的通信机制时,观察者模式是一种有效的选择。被观察者和观察者都只依赖于抽象接口,而不依赖于具体实现,使得系统更加灵活、可插拔。

  4. 当一个对象的状态变化会引发一系列相关操作和更新时,观察者模式可以避免显式地在对象之间进行紧密的耦合。被观察者只需通知观察者,而观察者可以根据自身的需求进行相应的操作,使得系统更加灵活和可维护。

  5. 当需要实现消息发布-订阅机制或事件驱动机制时,观察者模式是一种常见的设计选择。被观察者充当发布者,而观察者充当订阅者,通过观察者模式可以实现异步、松耦合的通信方式。

总之,观察者模式适用于多个对象之间存在一对多依赖关系,并且这些对象之间的状态变化需要及时通知其他对象的情况。它提供了一种灵活、解耦的方式来实现对象之间的通信和协作。


🍳参考文献

🧊文章总结

提示:这里对文章进行总结:

   本文讲了关于观察者模式的知识。






更多好文推荐

🍸2021-4月Python 机器学习——中文新闻文本标题分类
🍹2021年4月-(计算机网络)小型校园网络模拟搭建,最全最准确版
🍺2022-10-31-基于用户的协同过滤推荐算法实现+MAE+RMSE
🍻2022-11-28-大数据可视化,特征维度大于50
🥂2023-3-9-一篇简短的文章把C++左右值关系讲的透透彻彻

上一篇
End
下一篇

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

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

相关文章

【python手写算法】【多元】利用梯度下降实现线性拟合

本来是想做一个特征缩放的&#xff0c;然鹅发现我那种归一化缩放反而让训练速度变慢了。。先搞一个二元的。 if __name__ __main__:X1 [12.46, 0.25, 5.22, 11.3, 6.81, 4.59, 0.66, 14.53, 15.49, 14.43,2.19, 1.35, 10.02, 12.93, 5.93, 2.92, 12.81, 4.88, 13.11, 5.8,29.…

135432-37-0,Cyclo(-Gly-Arg-Gly-Asp-Ser-Pro)多肽合成(化学)方法

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ ---试剂基团反应特点&#xff08;Reagent group reaction characteristics&#xff09;--- 多肽试剂Cyclo(-Gly-Arg-Gly-Asp-Ser-Pro)&#xff08;CAS号&#xff1a;135432-37-0&#xff09;&#xff0c;目前多肽合成中&a…

左神算法中级提升(4) 超级重点:动态规划的空间压缩技巧

【案例1】 【题目描述】【以后出现这种的题型 概率很低】 【案例2】 【题目描述】 【思路解析】 构建两个栈&#xff0c;一个栈存放基本数据&#xff0c;一个栈存放最小值数据。每次加入一个数据时&#xff0c;当前元素和栈顶元素比较&#xff0c;谁小谁进入。 然后弹出时&a…

Hugging News #0710: 体验 MusicGen、Diffusers 库发布一周年、我们的内容政策更新

每一周&#xff0c;我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新&#xff0c;包括我们的产品和平台更新、社区活动、学习资源和内容更新、开源库和模型更新等&#xff0c;我们将其称之为「Hugging News」。本期 Hugging News 有哪些有趣的消息&#xff0…

[PyTorch][chapter 44][时间序列表示方法4]

前言&#xff1a; 训练复杂度 OE*T*Q 参数 全称 E 迭代次数 Number of the training epochs T数据集大小 Number of the words in the training set Q 模型计算复杂度 Model computational complexity E,T 一般都认为相同&#xff0c;所以这里面主要讨论Q&#xff0c;模…

maven-依赖管理-下

依赖冲突 特殊优先 特殊优先∶当同级配置了相同资源的不同版本&#xff0c;后配置的覆盖先配置的(提醒&#xff1a;要尽量避免这种没有意义的冲突)修改D:\java_projects\maven_A\pom.xml, 引入mysql5.1 <?xml version"1.0" encoding"UTF-8"?> &…

什么是用电信息采集系统?

用电信息采集系统是一种用于收集、处理和分析电力用户用电信息的系统&#xff0c;旨在提高电力系统的运行效率、可靠性和安全性。该系统主要通过对电力用户的用电数据进行实时监测、分析和处理&#xff0c;为电力公司、政府部门和用户提供有用的信息&#xff0c;以帮助他们更好…

PyTorch 1.13简介

# 1.  PyTorch 1.13 据官方介绍&#xff0c;PyTorch 1.13 中包括了 BetterTransformer 的稳定版&#xff0c;且不再支持 CUDA 10.2 及 11.3&#xff0c;并完成了向 CUDA 11.6 及 11.7 的迁移。此外 Beta 版还增加了对 Apple M1 芯片及 functorch 的支持。 1.1 主要更新 Be…

JavaWeb 前后端分离

AJax 1. 前端视图 ajax\src\main\webapp\ajax-register.html <html><head><meta charset"UTF-8"> </head><body><form class"form-horizontal" role"form"><div><tr><td>账号</td&…

数据库主从同步

目录 一、准备工作1.1 安装或关闭以下服务1.2 本次安装环境 2、主数据库配置2.1主数据库配置2.2创建用户2.3查看信息 三、从主数据库配置3.1从数据库配置3.2连接主服务器3.3测试 4、其他4.1连接完毕后发现Slave_IO_Running值异常&#xff0c;4.2报错Error connecting to source…

第一阶段-第七章 Python的函数进阶

目录 一、函数多返回值  1.学习目标  2.多个返回值的语法  3.本节的代码演示 二、函数多种传参方式  1.学习目标  2.函数参数种类&#xff08;位置参数、关键字参数、缺省参数、不定长参数&#xff08;位置传递、关键字传递&#xff09;&#xff09;  3.本节的代码…

一条命令解决端口占用,开启mysql

注&#xff1a;最后有面试挑战&#xff0c;看看自己掌握了吗 文章目录 端口占用开启mysql 端口占用 如果发现 8080 端口被占用可以使用命令 sudo lsof -t -i:8080 | sudo xargs kill -9 查找并杀死相应的进程。 开启mysql 打开命令提示符或终端。如果您已经安装了MySQL&…

【雕爷学编程】Arduino动手做(161)---16路PWM舵机驱动板PCA9685

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

HTML语法

文章目录 前言HTML 文件基本结构常见标签标签种类特殊符号图片链接a链接 双标签链接 列表表格 &#xff1a;表单多行文本域: 前言 HTML是有标签组成的 <body>hello</body>大部分标签成对出现. 为开始标签, 为结束标签. 少数标签只有开始标签, 称为 “单标签”. 开…

第二章:类和对象(中)

系列文章目录 文章目录 系列文章目录前言类的6个默认成员函数构造函数概念特性 析构函数概念特性 拷贝构造函数概念特征 赋值运算符重载运算符重载赋值运算符重载赋值运算符重载格式赋值运算符只能重载成类的成员函数不能重载成全局函数用户没有显式实现时&#xff0c;编译器会…

【物理】模拟粒子在电场和磁场中的轨迹研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Mysql的分库分表策略

一.水平切分 水平切分又称为 Sharding 策略&#xff0c;它是将同一个表中的记录拆分到多个结构相同的表中。 当一个表的数据不断增多时&#xff0c;Sharding 是必然的选择&#xff0c;它可以将数据分布到集群的不同节点上&#xff0c;从而缓存单个数据库的压力。 Sharding 策…

后端(五):JVM

目录 JVM 中的内存区域划分 JVM 的类加载机制 1. 加载 2. 验证 3. 准备 4. 解析 5. 初始化 JVM 中的垃圾回收策略 找&#xff0c;确认垃圾 1. 引用计数 2. 可达行分析 释放”垃圾“对象 1. 标记清除 2. 复制算法 3. 标记整理 分代算法 JVM也就是我们俗称的八股…

Bootstrap编写一个兼容主流浏览器的受众巨幕式风格页面

Bootstrap编写一个兼容主流浏览器的受众巨幕式风格页面 虽然说IE6除了部分要求苛刻的需求以外已经被可以不考虑了&#xff0c;但是WIN7自带的浏览器IE8还是需要支持的。 本文这个方法主要的优点&#xff0c;个人觉得就是准备少&#xff0c;不需要上网寻找大量的图片做素材&…

2003-Can‘t connect to Mysql server on ‘xxx‘ (10060 “Unknown error“)

Navicat连接 阿里云 服务器MySQL5.7数据库报错 解决办法&#xff1a; 进入数据库执行以下sql 1.允许root用户远程连接 GRANT ALL PRIVILEGES ON *.* TO root% IDENTIFIED BY 数据库密码 WITH GRANT OPTION; 2.刷新权限 FLUSH PRIVILEGES;3.执行quit退出数据库 quit; 4.…