观察者模式

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

描述

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 开放关闭原则” 的典型例子:

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

观察者和主体是解耦的:

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

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. 获取 + 查看 Android 源码的 方法

    Android源码获取方法. 作为一个Android开发者,必要的时候阅读以下源码可以拓宽一下自己的视野和对android的认知程度. Google的Android的源码管理仓库是用的是Git.And ...

  2. android 尺寸适配相关

    Android上常见度量单位 px(像素):屏幕上的点,绝对长度,与硬件相关. in(英寸):长度单位. mm(毫米):长度单位. pt(磅):1/72英寸,point. dp(与密度无关的像素):一 ...

  3. Elasticsearch 6.8.6

    mac;centos;unix;  下载 wget  https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.6. ...

  4. 秋招过半零Offer怎么办?

    参加今年秋招的同学都知道,尤其是双非本科更是体验深刻.9 月份至今,面试寥寥无几.笔试也不是很多,大中小公司 Offer 没拿下一个.作为应届生的我们,该怎么办呢? 1.调整好心态 这个世界上有两种事 ...

  5. 如何用CRM销售管理系统实现销售目标?

    每个企业的销售业务都要制定目标计划,在制定销售计划时要考虑两个问题,一个是计划是否能够严格执行,另一个是计划是否可控,即明确销售目标后,合理分配时间,运用销售基本工作方法严格把控销售进度.那我们该如何 ...

  6. umich cv-4-2 经典卷积网络架构

    这节课中主要讨论了卷积神经网络的发展历史以及几种经典结构是如何构建的 卷积网络经典结构 AlexNet VGG GoogleNet Residual Network AlexNet 在2012年的时候 ...

  7. 推理(Inference)与预测(Prediction)

    在机器学习的背景下,很多人似乎混淆了这两个术语.这篇文章将试图澄清我们所说的这两个词是什么意思,每一个词在哪里有用,以及它们是如何应用的.在这里,我将举几个例子来直观地理解两者之间的区别. 推理和预测 ...

  8. SNN_STDP

    STDP 是一种时间不对称的Hebbian学习形式,由突触前和突触后神经元的脉冲时间的时间相关性引起的.是一种双向Hebbian学习法则. 突触权重变化\(\Delta w\)依赖于突触前脉冲的到达和 ...

  9. VUE首屏加载优化 性能优化分析插件安装分享

    优化背景: 项目上线后 第一次进入项目要等待接近50s才能进入页面.一开始觉得是电脑配置问题或者网络问题.F12后发现加载资源过慢 其中一个chunk-***js文件有10m 加载了45s .我们使用 ...

  10. Webpack.devServer 配置项如何使用?附devServer完整示例

    前言: 我们在平常本地开发时,可能经常需要与后端进行联调,或者调用一些api,但是由于浏览器跨域的限制.开发与生产环境的差异.http与https等问题经常让联调的过程不够顺畅.所以本文介绍一下web ...