观察者模式

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

描述

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. JS逆向实战23 某市wss URL加密+请求头+ws收发

    声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 本文首发链接为: http ...

  2. 前端三件套系例之JS——JS的BOM操作、JS的DOM操作

    文章目录 1 JS的BOM操作 1.介绍 2.window对象 2-1 代码 3.window的子对象 3-1 navigator对象(了解即可) 3-2 screen对象(了解即可) 3-3 his ...

  3. 为何 DevOps 会给开发人员带来压力和倦怠?

    企业正在享受 DevOps 实施带来的好处,但这也是有代价的.开发人员需要承担额外的责任,可能会导致他们感到疲惫不堪.因此我们可以采取一些方法来确保 DevOps 工程师的满意度. DevOps 的支 ...

  4. 一个类似于Gridster的栅格布局系统Vue组件

    哈喽,我是老鱼,一名致力于在技术道路上的终身学习者.实践者.分享者! Vue Grid Layout是一个类似于Gridster的栅格布局系统, 适用于Vue.js,灵感来源于React Grid L ...

  5. 把工单历史表中的数据,按照工单进行分类,每一批工单的数据放在同一个 key 中

    /** * 把工单历史表中的数据,按照工单进行分类,每一批工单的数据放在同一个key中 * 将对象列表按名称分类成 Map(分类名必与对象的某 get 方法的后的名一致<如:get(name) ...

  6. [Python急救站课程]斐波那契数列的计算吧

    斐波那契数列的计算 a, b = 0, 1 while a < 1000: # 输出不大于1000 的序列.while表示循环 print(a, end=',') a, b = b, a + b

  7. Python 既是解释型语言,也是编译型语言

    哈喽大家好,我是咸鱼 不知道有没有小伙伴跟我一样,刚开始学习 Python 的时候都听说过 Python 是一种解释型语言,因为它在运行的时候会逐行解释并执行,而 C++ 这种是编译型语言 不过我今天 ...

  8. vue 项目中遇到的问题及解决方案

    问题:从码云上提前代码时npm run dev 报错 解决方法 在目录外层新建一个postcss.config.js 放入以下代码 module.exports = {       plugins:  ...

  9. vue中export default function 和 export function 的区别

    export default function 和 export function 的区别 // 第一种 export default function crc32() { // 输出 // ... ...

  10. Vite4+Typescript+Vue3+Pinia 从零搭建(4) - 代码规范

    项目代码同步至码云 weiz-vue3-template 要求代码规范,主要是为了提高多人协同和代码维护效率,结合到此项目,具体工作就是为项目配置 eslint 和 prettier. editorc ...