3.观察者模式C++用法示例

2023-11-02

一.观察者模式

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,当主题对象状态发生改变时,会通知所有观察者对象,使它们自动更新自己。

1.作用

观察者模式的主要作用在于解耦观察者和被观察者,使它们之间的依赖关系变得松散,从而提高系统的可扩展性和可维护性。观察者模式还有以下的作用:

  1. 支持广播通信:当一个对象发生改变时,所有依赖于它的对象都会收到通知,这样就可以实现对象间的广播通信。
  2. 提供面向对象设计的基础:观察者模式将观察者和被观察者之间的关系抽象化,使得它们可以独立地变化,从而更好地支持面向对象设计的原则。
  3. 降低系统的耦合度:观察者模式可以将观察者和被观察者之间的依赖关系解耦,从而降低系统的耦合度,使得系统更加灵活、可扩展和可维护。
  4. 支持事件驱动编程:观察者模式可以将事件的发布和订阅抽象化,从而支持事件驱动编程,这在GUI编程、网络编程等领域中非常常见。

2.适用场景

观察者模式适用于那些需要解耦观察者和被观察者之间的依赖关系,同时需要实现多个对象之间的通信和协作的场景。

  1. GUI(图形用户界面)开发:在 GUI 应用程序中,我们经常需要更新多个 UI控件的状态,以响应用户输入或其他操作。这些控件可能来自不同的类,但它们需要共享某些数据。这时候,我们可以使用观察者模式来解耦控件之间的依赖关系。
  2. 网络编程:在分布式系统中,通常需要处理大量的网络事件和消息,例如客户端连接、断开、数据传输等。这时候,我们可以使用观察者模式来简化事件和消息的处理。
  3. 日志记录:在大型应用程序中,日志记录是必不可少的。观察者模式可以让我们将日志记录器与日志处理器解耦,从而提高代码的可维护性和扩展性。
  4. 数据库设计:在数据库设计中,我们可以使用观察者模式来实现触发器(trigger)的功能。触发器可以在数据库中的某个表发生变化时自动触发一些操作,例如更新其他表的数据、发送邮件通知。
  5. 事件驱动编程:在事件驱动编程中,我们可以使用观察者模式来实现事件的注册和处理。事件可以是用户输入、硬件事件、系统消息等。当事件发生时,观察者模式可以自动通知所有的事件处理器进行处理。

3.实现要素

  1. Subject——抽象主题(抽象被观察者):抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
  2. ConcreteSubject——具体主题(具体被观察者):该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
  3. Observer——抽象观察者:是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
  4. ConcrereObserver——具体观察者:实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

二.C++程序示例

#include <iostream>
#include <vector>

class Observer { // 抽象观察者
public:
    virtual void update() = 0;
};

class Subject { // 抽象主题
public:
    virtual void attach(Observer* observer) = 0;
    virtual void detach(Observer* observer) = 0;
    virtual void notify() = 0;
};

class Cart : public Subject { // 具体主题
private:
    std::vector<Observer*> observers;
    int totalPrice;
public:
    void attach(Observer* observer) override {
        observers.push_back(observer);
    }

    void detach(Observer* observer) override {
        observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());
    }

    void notify() override {
        for (auto observer : observers) {
            observer->update();
        }
    }

    void setTotalPrice(int price) {
        totalPrice = price;
        notify();
    }

    int getTotalPrice() const {
        return totalPrice;
    }
};

class Customer : public Observer { // 具体观察者
private:
    std::string name;
    Cart* cart;
public:
    Customer(std::string name, Cart* cart) : name(name), cart(cart) {}

    void update() override {
        std::cout << name << " receives the updated cart total price: $" << cart->getTotalPrice() << std::endl;
    }
};

int main() {
    Cart* cart = new Cart();
    Customer* customer1 = new Customer("Alice", cart);
    Customer* customer2 = new Customer("Bob", cart);

    cart->attach(customer1);
    cart->attach(customer2);

    cart->setTotalPrice(100);

    cart->detach(customer2);

    cart->setTotalPrice(200);

    delete cart;
    delete customer1;
    delete customer2;

    return 0;
}

在这里插入图片描述

Subject 抽象主题,定义了增加、删除观察者和通知观察者的接口。
Cart 具体主题,实现了抽象主题的接口,维护了一个观察者列表,以及具体状态。
Observer 抽象观察者,定义了一个更新接口。
Customer 具体观察者,实现了抽象观察者的接口,持有具体主题的引用,在状态改变时接收通知并做出相应的响应。
在 main 函数中创建具体主题和具体观察者对象,并对其进行操作,以此演示观察者模式的工作方式。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

3.观察者模式C++用法示例 的相关文章

  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 重载<<的返回值

    include
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • IEnumreable 动态和 lambda

    我想在 a 上使用 lambda 表达式IEnumerable
  • 如何将服务器服务连接到 Dynamics Online

    我正在修改内部管理应用程序以连接到我们的在线托管 Dynamics 2016 实例 根据一些在线教程 我一直在使用OrganizationServiceProxy out of Microsoft Xrm Sdk Client来自 SDK
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co

随机推荐

  • 利用keras自带影评数据集进行评价正面与否的二分类训练

    1 from keras datasets import imdb 2 from keras import layers 3 from keras import models 4 from keras import optimizers 5
  • 王学丹 确定测试原始需求

  • g2plot 水滴图,包含数据更新时渲染问题

    官网地址 https g2plot antv vision zh docs manual introduction 第一步 vue安装对应插件 网上很多 可以百度一下 npm install antv g2plot save 第二步 引入
  • Class.forName用法(详解)

    主要功能 Class forName xxx xx xx 返回的是一个类 Class forName xxx xx xx 的作用是要求JVM查找并加载指定的类 也就是说JVM会执行该类的静态代码段 下面 通过解答以下三个问题的来详细讲解下C
  • Word embedding techniques

    Word embedding techniques Word embedding techniques are methods used to represent words in a numerical format such as a
  • 文件相关操作

    1 文件相关概念 1 1文件的概念 一个文件通常就是磁盘上一段命名的存储区 但是对于操作系统来说 文件就会更复杂一些 例如 一个大文件可以存储在一些分散的区段中 或者还会包含一些操作系统可以确定其文件类型的附加数据 但是这些是操作系统 而不
  • 安卓逆向(工具篇)

    安卓逆向 1 下载工具 1 apktool 可以反编译软件的布局文件 图片等资源 方便大家学习一些很好的布局 2 dex2jar 将apk反编译成java源码 classes dex转化成jar文件 3 jd gui 查看APK中class
  • java 微信开发图片发送,微信开发?Java上传Base64图片

    class java gt import org apache commons codec binary Base64 import org apache log4j LogManager import org apache log4j L
  • 2021-07-11 layer与tier的区别(英语)

    layer与tier的区别 英语 都是层的意思 但是两个词不太一样 layer指的是多层相同的东西 比如天冷的时候盖两层被 用layer tier指的是多层不同的东西 以某种目的叠加在一起 起到一定作用 比如人的消化系统有三个层次 咀嚼破碎
  • SpringCloud集成RocketMQ实现事务消息方案

    前边的话 当前SpringCloud作为微服务开发的首选开源方案提供了完善的微服务开发技术套件 不过针对分布式领域的难题 分布式事务控制并没有成熟的方案 本篇将介绍作为柔性事务控制的优秀方案RocketMQ的使用原理和方法 通过本案例的学习
  • 升级你的GitHub终端认证方式:从密码到令牌

    升级你的GitHub终端认证方式 从密码到令牌 前言 GitHub官方在2021年8月14日进行了一次重大改变 它将终端推送代码时所需的身份认证方式从密码验证升级为使用个人访问令牌 Personal Access Token 这个改变引起了
  • 三角剖分算法(delaunay)

    开篇 在做一个Low Poly的课题 而这种低多边形的成像效果在现在设计中越来越被喜欢 其中的低多边形都是由三角形组成的 而如何自动生成这些看起来很特殊的三角形 就是本章要讨论的内容 项目地址 https github com zhiyis
  • 阿里云OSS对象存储上传文件(一)SDK安装

    因为实际项目需求 需要使用阿里云oss的对象存储来上传文件 在写代码操作之前 需要先安装SDK 编译你能使用的lib 其实前后找了不少文章 但都不太细致 所以分享一下我本人使用的经验 不代表适用所有人 仅供参考 环境是windows系统 v
  • 安装使用NVIDIA-Docker——可使用GPU的Docker容器

    参考网址 https www cnblogs com wuchangsoft p 9767074 html nvidia docker是一个可以使用GPU的docker nvidia docker是在docker上做了一层封装 通过nvid
  • 【LeetCode题解】子序列问题

    文章目录 参考资料 子序列问题模板 动态规划 一 两种思路 例题 128 最长连续序列 思路一 代码 动态规划设计 300 最长递增子序列 动态规划设计 1143 最长公共子序列 动态规划设计 516 最长回文子序列 392 判断子序列 参
  • Java发布webservice

    先附上一个webservice的视频教程 链接 https pan baidu com s 1qesv A7cp zYsL7fE5nmFw 提取码 3d6k 创建服务端 提供接口 方式一 创建一个web工程 创建一个ServiceHello
  • C++ list容器

    1 list容器基本概念 循环迭代器 链表的末尾指向链表的链头 链表的链头指向链表的链尾 链表迭代器支持前移和后移 也就是说支持 和 操作 但不支持 n 和 n 操作 不支持随机访问 2 链表构造函数 3 赋值和交换 4 大小操作 5 插入
  • 基于实例讲解lsqcurvefit参数用法

    本博文源于 数学建模 旨在讲解非线性最小二乘拟合的MATLAB实现 谈到matlab中非线性最小二乘拟合 就不得不提到lsqcurvefit与lsqnonlin 博文就讲解一下lsqcurvefit如何使用 一 函数基本用法讲解 x lsq
  • Element-UI开发指南--动画和组件基础(二)

    文章目录 内置过渡动画 fade 淡入淡出 zoom 缩放 collapse 展开折叠 组件 Layout 布局 基础布局 分栏间隔 混合布局 分栏偏移 对齐方式 响应式布局 基于断点的隐藏类 Row 属性 Col 属性 Container
  • 3.观察者模式C++用法示例

    观察者模式 一 观察者模式 1 作用 2 适用场景 3 实现要素 二 C 程序示例 一 观察者模式 观察者模式 Observer Pattern 是一种行为型设计模式 它定义了一种一对多的依赖关系 让多个观察者对象同时监听一个主题对象 当主