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



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

💥💥💥欢迎来到🤞汤姆🤞的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.mzph.cn/news/2233.shtml

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

相关文章

opencv-06 使用numpy.array 操作图片像素值

opencv-06 使用numpy.array 操作图片像素值 **1&#xff0e;二值图像及灰度图像****利用item 读取某一个像素值****利用itemset 修改像素值****彩色图像numpy.arry 像素值操作** numpy.array 提供了 item()和 itemset()函数来访问和修改像素值&#xff0c;而且这两个函数都是经…

基于MATLAB的无人机遥感数据预处理与农林植被性状估算

查看原文>>>基于MATLAB的无人机遥感数据预处理与农林植被性状估算 在新一轮互联网信息技术大发展的现今&#xff0c;无人机、大数据、人工智能、物联网等新兴技术在各行各业都处于大爆发的前夜。为了将人工智能方法引入农业生产领域。首先在种植、养护等生产作业环节…

Offset Explorer2 监视kafka的利器

kafka作为一个生产者和消费者集为一体的框架&#xff0c;消费者必须一直保持打开的状态&#xff0c;并且每隔一段时间接收一次数据&#xff0c;才能够保持生产者放入的数据及时被处理掉&#xff0c;而生产者则可以每隔一段时间发送一波数据&#xff0c;这样消费者就能够接收到了…

layui入门增删改查

layui入门增删改查 创建Lauiyi对象1.后台准备1.dao方法2.子实现类 2.R工具类的使用3.查询前端代码实现前端页面 4.增删改实现2.浮层3分离的js代码1.userManage.js2.userEdit.js3.index.js 5.运行效果 作为一名开发人员&#xff0c;我们经常需要对数据库中的数据进行增删改查&am…

前端node.js入门

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 Node.js 入门 什么是 Node.js&#xff1f; 什么是前端工程化&#xff1f; Node.js 为何能执行 JS&…

【数据结构】二叉树详解(2)

⭐️ 前言 ✨ 往期文章链接&#xff1a;二叉树的概念性质 上一篇我们讲了二叉树的结构定义&#xff0c;以及前序/中序/后序的递归遍历&#xff0c;还有一些二叉树的接口实现&#xff0c;本篇我们补充一个二叉树的接口 BinaryTreeDepth。✨上一篇文章链接&#xff1a;二叉树详…

结合ChatGPT制作PPT

今天看到圈友的一个AI分享&#xff0c;然后自己本身需要做一个分享的PPT。刚好那着帖子实战一下。先说下整体感受。 优点&#xff1a;制作成本确实会比较低&#xff0c;很熟练的话大概就是1分钟一个都有可能。整体流程是先找个第三方PPT制作网站&#xff0c;看下支不支持文本转…

PLEX如何搭建个人局域网的视频网站

Plex是一款功能非常强大的影音媒体管理系统&#xff0c;最大的优势是多平台支持和界面优美&#xff0c;几乎可以在所有的平台上安装plex服务器和客户端&#xff0c;让你可以随时随地享受存储在家中的电影、照片、音乐&#xff0c;并且可以实现观看记录无缝衔接&#xff0c;手机…

opencv-14 图像加密和解密

在OpenCV中&#xff0c;图像加密和解密是通过对图像像素进行一系列的变换和操作来实现的 通过按位异或运算可以实现图像的加密和解密。 通过对原始图像与密钥图像进行按位异或&#xff0c;可以实现加密&#xff1b;将加密后的图像与密钥图像再次进行按位异或&#xff0c;可以实…

实例019 以图形按钮显示的界面

实例说明 菜单和工具栏虽然能方便用户操作程序的相应功能&#xff0c;但各有缺点。如果采用按钮式功能菜单&#xff0c;不但美观大方&#xff0c;而且操作灵活。当单击按钮时&#xff0c;用户区将显示相应的操作按钮组。下面介绍图形界面式菜单的设计方法。运行本例&#xff0…

【贪心算法Part03】| 1005.K次取反后最大化的数组和、134.加油站、135.分发糖果

目录 &#x1f388;LeetCode1005.K次取反后最大化的数组和 &#x1f388;LeetCode134.加油站 &#x1f388;LeetCode135.分发糖果 &#x1f388;LeetCode1005.K次取反后最大化的数组和 链接&#xff1a;1005.K次取反后最大化的数组和 给你一个整数数组 nums 和一个整数 k…

分享一个唯美雪花界面

先看效果&#xff1a; 再看代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>雪</title><meta name"viewport" content"widthdevice-width, initial-scale1&…

TKDE论文,跑的改的,GPSCVULDETECTOR

Combining Graph Neural Networks With Expert Knowledge for Smart Contract Vulnerability Detection 论文代码GitHub https://github.com/Messi-Q/GPSCVulDetectorpaper https://ieeexplore.ieee.org/abstract/document/9477066/参考IJCAI 21中AME的数据集 https://gith…

中国地图使用心得

中国地图使用心得 注册地图是注册在echarts对象上而非 自己构建的echarts dom上、。 请求本地json文件 ​ vue项目的public打包时不会动&#xff0c;所以线上和本地地址直接指向了public同级目录&#xff0c;请求时直接相对路径 绘制中国地图时&#xff0c;如何在各个省会地方…

旅游卡系统加盟代理软件开发

旅游行业的不断发展&#xff0c;越来越多的旅行社开始推出各种优惠卡来吸引游客。而随着智能手机的普及&#xff0c;开发一款旅行社优惠卡APP软件成为了一种必然的趋势。 该软件的主要功能是提供旅行社的各种优惠卡信息&#xff0c;包括优惠卡的种类、价格、使用范围、有效…

无极低代码,免费工具在线实用工具分享

在当今数字化的时代&#xff0c;我们需要尽可能地减少手动操作&#xff0c;提高工作效率。这就是为什么我们需要一些在线工具来帮助我们完成一些繁琐的任务。以下是一些无极低代码网集成的在线工具&#xff0c;可以帮助您更快、更轻松地完成任务。 项目管理 项目周期计算&…

ARP解析MAC地址的全过程(ARP的工作机制)

目录 ARP解析MAC地址的过程&#xff1a; 源码等资料获取方法 以太网环境下&#xff0c;同一个网段的主机之间需要互相知道对方的MAC地址&#xff0c;才能访问。 TCP/IP协议栈从上层到下层的封装过程中&#xff0c;第三层封装需要知道目的IP&#xff0c;第二层封装需要知道目…

Java 设计模式——迭代器模式

目录 1.概述2.结构3.案例实现3.1.抽象迭代器3.2.具体迭代器3.3.抽象聚合3.4.具体聚合3.5.测试 4.优缺点5.使用场景6.JDK 源码解析——Iterator 1.概述 迭代器模式 (Iterator Pattern) 是一种行为型设计模式&#xff0c;它提供一种顺序访问聚合对象&#xff08;如列表、集合等&…

使用亚马逊(AWS)云服务在S3上实现图片缩放功能(CloudFront/S3[AccessPoint/LambdaAccessPoint])

亚马逊云服务中的S3对象存储功能和国内阿里云的oss对象存储使用基本一致。但是涉及到存储内容处理时&#xff0c;两家有些差别。 比如&#xff1a;对于云存储中的图片资源&#xff0c;阿里云比较人性化对于基本的缩放裁剪功能已经帮我们封装好了&#xff0c;只需要在url地址后…

Bean 作用域与生命周期

Bean 作用域与生命周期 ​ 对于 Spring 来说&#xff0c;核心操作对象就是存和取 Bean &#xff0c;接下来就 Bean 的作用域与生命周期进行探讨。 文章目录 Bean 作用域与生命周期一、作用域的定义1.1、Bean 的6种作用域1.2、Bean作用域设置方法 二、Bean 的生命周期2.1、Bean…