观察者模式

主体(被观察者)通知一个或多个观察者状态改变/数据更新/事件发生。

描述

C++ 实现观察者模式有几个要点:

  1. 观察者都有一个共同的抽象基类 Listener,定义了一个纯虚接口 OnNotified(),主体调用该接口通知观察者
  2. 每个观察者 ConcreteListener 继承自抽象基类 Listener,并实现 OnNotified() 方法
  3. 主体提供了注册 Listener 的方法 RegisterListener(Listener&),内部通过 vector 维护 listener 列表;当主体需要通知观察者时,遍历观察者列表,对每个观察者调用其 OnNotified() 方法。此处用了面向对象中的多态,即 vector 中保存的是各个 Listener 的指针或引用,主体只依赖 Listener 的抽象接口,无需关心观察者的具体类型。因为 vector 不能直接保存引用,可以使用指针或者 std::reference_wrapper<Listner>
  4. 主体也可以根据需要,提供 UnregisterListener 方法,观察者也可能需要保存主体的指针或引用,用于之后的 Unregister。

示例代码

#include <functional>
#include <vector> class Listener {
public:
virtual ~Listener() = default;
virtual void OnNotified() = 0;
// 如果需要传递数据,可以在 OnNotified 接口中增加参数
// virtual void OnNotified(const Data&) = 0;
}; class ConcreteListener : public Listener {
public:
void OnNotified() override {}
}; class Subject {
public:
void RegisterListener(Listener& o) {
listeners_.push_back(o);
} private:
void NotifyListeners() {
for (Listener& o : listeners_) {
o.OnNotified();
}
} // 注意:vector 不能停直接保存引用,可以用 reference_wrapper
std::vector<std::reference_wrapper<Listener>> listeners_;
};

传递数据的两种机制:Push 和 Pull

注意:在这个例子中,主体只是通知观察者,如果需要传递信息,有两种做法:

  • Push 推:直接在 OnNotified() 函数中增加参数,如 OnNotified(const Data&)。但是不同的观察者可能需要 Data 中的不同数据
  • Pull 拉:OnNotified() 不带参数,只负责通知变化,主体提供一组额外的 Getter 方法,当观察者收到通知时,根据自身需要,调用不同的 Getter 方法获取特定数据。

这两种方法都可以,实际项目中 Push 的方式更常见。

观察者模式的好处

观察者模式是 SOLID 原则中,遵循 “OCP 开放关闭原则” 的典型例子:

  • 对扩展开放:新的观察者只需要实现 ListenerOnNotified() 接口,并向主体注册即可
  • 对修改关闭:现有代码(主体的代码、其他观察者的代码)不需要修改

观察者和主体是解耦的:

  • 主体不了解观察者的细节,只知道观察者实现了 OnNotified() 接口
  • 观察者对主体也所知甚少,只知道主体提供了 RegisterListener(Listener& l) 方法,并通过 ListenerOnNotified() 方法通知观察者。

C++ 观察者模式实现的更多相关文章

  1. 23种设计模式--观察者模式-Observer Pattern

    一.观察者模式的介绍      观察者模式从字面的意思上理解,肯定有两个对象一个是观察者,另外一个是被观察者,观察者模式就是当被观察者发生改变得时候发送通知给观察者,当然这个观察者可以是多个对象,在项 ...

  2. 谈谈JS的观察者模式(自定义事件)

    呼呼...前不久参加了一个笔试,里面有一到JS编程题,当时看着题目就蒙圈...后来研究了一下,原来就是所谓的观察者模式.就记下来...^_^ 题目 [附加题] 请实现下面的自定义事件 Event 对象 ...

  3. ObserverPattern(观察者模式)

    import java.util.ArrayList; import java.util.List; /** * 观察者模式 * @author TMAC-J * 牵一发而动全身来形容观察者模式在合适 ...

  4. java观察者模式

      像activeMQ等消息队列中,我们经常会使用发布订阅模式,但是你有没有想过,客户端时如何及时得到订阅的主题的信息?其实就里就用到了观察者模式.在软件系统中,当一个对象的行为依赖于另一个对象的状态 ...

  5. Backbone源码解析(六):观察者模式应用

    卤煮在大概一年前写过backbone的源码分析,里面讲的是对一些backbone框架的方法的讲解.这几天重新看了几遍backbone的源码,才发现之前对于它的理解不够深入,只关注了它的一些部分的细节和 ...

  6. PHP 高级编程(3/5) - 使用SPL(标准PHP库)实现观察者模式

    SPL(标准PHP库 - Standard PHP Library)是PHP5面向对象功能中重要的部分.原文解释是这样的“The Standard PHP Library (SPL) is a col ...

  7. 设计模式--观察者模式初探和java Observable模式

    初步认识观察者模式 观察者模式又称为发布/订阅(Publish/Subscribe)模式,因此我们可以用报纸期刊的订阅来形象的说明: 报社方负责出版报纸. 你订阅了该报社的报纸,那么只要报社发布了新报 ...

  8. 学C#之设计模式系列笔记(2)观察者模式

    一.借鉴说明 1.<Head First Design Patterns>(中文名<深入浅出设计模式>) 2.维基百科,观察者模式,https://zh.wikipedia.o ...

  9. PHP 观察者模式

    观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. [观察者模式中主要角色] 1.抽象主题(Subject)角色: 抽象主题提供了增加 ...

  10. GJM: 设计模式 - 观察者模式

    GJM : 观察者模式 视频地址: http://www.imooc.com/learn/415 本课程通过一个天气预报的发布和订阅案例,来讲解观察者模式在Java项目中的应用.主要包括观察者模式的结 ...

随机推荐

  1. 其它——Siege压力测试工具使用

    文章目录 Siege压力测试工具使用 一 Siege介绍 二 windows 下使用 三 mac和linux使用 四 使用 五 参数详解 六 结果详解 七 修改系统的文件描述符限制 Siege压力测试 ...

  2. Java开发面试--群面专区

    目录 一.群面背景 二.群面流程 三.群面角色 四.群面细节 五.群面礼仪 六.群面话术 七.个人演讲 八.群面题型 群面也称无领导小组~ 候选人们被要求在一个相对自由的环境中展示他们的能力,并在没有 ...

  3. js数据结构--集合

    <!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...

  4. 怎么用Python写一个浏览器集群框架

    这是做什么用的 框架用途 在采集大量新闻网站时,不可避免的遇到动态加载的网站,这给配模版的人增加了很大难度.本来配静态网站只需要两个技能点:xpath和正则,如果是动态网站的还得抓包,遇到加密的还得j ...

  5. 实战攻防演练-利用Everything搜索软件进行内网后渗透利用

    前言 Everything是一款很出名的文件搜索工具,基于文件.文件夹名称的快速搜索的轻量级的软件,而早在几年前就有很多apt组织利用everything来进行文件查找等,前几年在T00ls上也有人发 ...

  6. 工控机中部署Ubuntu 22.04 系统

    1.下载Ubuntu系统服务器版本 获取Ubuntu服务器版 | Ubuntu 2.下载启动盘制作工具 UltralSO(试用就可以) 文件 > 打开(Ubuntu.ISO) > 启动 & ...

  7. 自然语言处理历史史诗:NLP的范式演变与Python全实现

    本文全面回顾了自然语言处理(NLP)从20世纪50年代至今的历史发展.从初创期的符号学派和随机学派,到理性主义时代的逻辑和规则范式,再到经验主义和深度学习时代的数据驱动方法,以及最近的大模型时代,NL ...

  8. 初窥门径,从大模型到内容生成看AI新次元

    视频云AI进化新纪元. 最近Gartner发布2024年十大战略技术趋势,AI显然成为其背后共同的主题.全民化的生成式人工智能.AI增强开发.智能应用......我们正在进入一个AI新纪元. 从Cha ...

  9. C#中LINQ的使用知多少?LINQ常功能整理,实例源代码解析

    LINQ(Language-Integrated Query)是C#语言中的一个强大的查询技术,它提供了一种统一的查询语法,可以用于查询和操作各种数据源,包括集合.数据库.XML等.下面详细描述了LI ...

  10. 【Javaweb】Servlet八 | 请求转发的代码实现【详解】

    请求的转发 什么是请求的转发? 请求转发是指,服务器收到请求时,从一次资源转到另一个资源的操作叫做请求转发. 部分代码 // 获取请求的参数(办事的材料)查看 String username=req. ...