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.hqwc.cn/news/21438.html

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

相关文章

Linux离线安装Jenkins、Maven、Gitlab、Git,部署Java项目

安装Java 《Linux安装java》 安装Maven 把Maven上传到Linux服务器/data/目录下进行解压 cd /data/ && tar -zxvf apache-maven-3.9.3-bin.tar.gz配置环境变量 vim /etc/profile找到export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL在下面追加 # mave…

Java基础---集合类

目录 典型回答 Collection和Collections有什么区别 Java中的Collection如何遍历迭代 Iterable和Iterator如何使用 为什么不把Iterable和Iterator合成一个使用 哪些集合类是线程安全的 典型回答 什么是集合 集合就是一个放数据的容器&#xff0c;准确的说是放数据对象引用…

Tomcat 基础

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、概述 二、安装 三、 目录结构 四、启停 五、配置文件 1. server.xml (1) Server (2) Listener (3) GlobalNamingResources (4) Service 01.Connector (1) port…

Unity知识记录--项目升级URP

URP是指Unity的通用渲染管线&#xff0c;此处主要针对原有项目进行升级使用&#xff0c;但并不是所有的内容都可以直接通过升级完成&#xff0c;直接使用的Unity默认的shader通常可以完成直接升级&#xff0c;自己编写的shader通常需要重做。 首先我们先要安装这个Package&…

Centos 7 安装 Oracle 11G

Oracle 11G 安装教程 准备环境 p13390677_112040_Linux-x86-64_1of7.zipp13390677_112040_Linux-x86-64_2of7.zipCentos 7- rhel7-英文版的系统–不想换语言的执行(LANGen_US)– 传输 文件到服务器上 创建用户和组 [rootlocalhost ~]# groupadd oracle [rootlocalhost ~]…

12.4 ARM异常处理

目录 ARM异常处理&#xff08;一&#xff09; 异常 概念 异常处理机制 ARM异常源 概念 ARM异常源 ARM异常模式 ARM异常处理&#xff08;二&#xff09; ARM异常响应 异常向量表 异常返回 IRQ异常举例​编辑 ARM异常处理&#xff08;三 &#xff09; 异常优先级 …

深入理解netfilter和iptables

目录 Netfilter的设计与实现 内核数据包处理流 netfilter钩子 钩子触发点 NF_HOOK宏与Netfilter裁定 回调函数与优先级 iptables 内核空间模块 xt_table的初始化 ipt_do_table() 复杂度与更新延时 用户态的表&#xff0c;链与规则 conntrack Netfilter(结合iptable…

计算机网络概述(一)

因特网概述 网络&#xff0c;互联网与因特网的区别联系&#xff1a; 以上是使用有线和无线链路连接的两个网络。那么&#xff0c;要让这两个网络连接起来&#xff0c;就需要路由器。若干个网络通过多个路由器互联起来&#xff0c;就称为了互联网。 因特网是当今世界上最大的互…

prometheus采集服务的jmx数据,grafana通过dashboard展示jmx数据

prometheus采集服务的jmx数据&#xff0c;grafana通过dashboard展示jmx数据 一、下载prometheus二、解压prometheus三、查看prometheus目录四、查看prometheus版本五、查看prometheus的配置文件六、启动prometheus七、登陆prometheus八、查看prometheus jmx九、下载grafana十、…

Orangepi Zero2 全志H616简介

一、简介 Linux 系统 &#xff0c;平台是 ARM 架构 特性 CPU 全志H616四核64位1.5GHz高性能Cortex-A53处理器 GPU MaliG31MP2 SupportsOpenGLES1.0/2.0/3.2、OpenCL2.0 运行内存 1GBDDR3(与GPU共享&#xff09; 存储 TF卡插槽_16G,测试128G可支持、2MBSPIFlash WIFI蓝牙 AW8…

kettle开发-Day40-AI分流之case/switch

前言&#xff1a; 前面我们讲到了很多关于数据流的AI方面的介绍&#xff0c;包括自定义组件和算力提升这块的&#xff0c;今天我们来学习一个关于kettle数据分流处理非常重要的组件Switch / Case 。当我们的数据来源于类似日志、csv文件等半结构化数据时&#xff0c;我们需要在…

node.js

文章目录 包含Buffer概述创建操作 软件运行过程线程与进程fs模块写入文件追加流式写入使用场景 读取文件文件流式读取读取场景 复制案例内存占有量 重命名和移动删除文件夹操作创建读取删除 查看文件的资源相对路径bug path模块http协议创建http服务器x获取请求体获取请求报文案…