C++ 观察者模式实现
观察者模式
主体(被观察者)通知一个或多个观察者状态改变/数据更新/事件发生。
描述

C++ 实现观察者模式有几个要点:
- 观察者都有一个共同的抽象基类
Listener,定义了一个纯虚接口OnNotified(),主体调用该接口通知观察者 - 每个观察者
ConcreteListener继承自抽象基类Listener,并实现OnNotified()方法 - 主体提供了注册
Listener的方法RegisterListener(Listener&),内部通过vector维护 listener 列表;当主体需要通知观察者时,遍历观察者列表,对每个观察者调用其OnNotified()方法。此处用了面向对象中的多态,即vector中保存的是各个 Listener 的指针或引用,主体只依赖 Listener 的抽象接口,无需关心观察者的具体类型。因为vector不能直接保存引用,可以使用指针或者std::reference_wrapper<Listner> - 主体也可以根据需要,提供
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++ 观察者模式实现的更多相关文章
- 23种设计模式--观察者模式-Observer Pattern
一.观察者模式的介绍 观察者模式从字面的意思上理解,肯定有两个对象一个是观察者,另外一个是被观察者,观察者模式就是当被观察者发生改变得时候发送通知给观察者,当然这个观察者可以是多个对象,在项 ...
- 谈谈JS的观察者模式(自定义事件)
呼呼...前不久参加了一个笔试,里面有一到JS编程题,当时看着题目就蒙圈...后来研究了一下,原来就是所谓的观察者模式.就记下来...^_^ 题目 [附加题] 请实现下面的自定义事件 Event 对象 ...
- ObserverPattern(观察者模式)
import java.util.ArrayList; import java.util.List; /** * 观察者模式 * @author TMAC-J * 牵一发而动全身来形容观察者模式在合适 ...
- java观察者模式
像activeMQ等消息队列中,我们经常会使用发布订阅模式,但是你有没有想过,客户端时如何及时得到订阅的主题的信息?其实就里就用到了观察者模式.在软件系统中,当一个对象的行为依赖于另一个对象的状态 ...
- Backbone源码解析(六):观察者模式应用
卤煮在大概一年前写过backbone的源码分析,里面讲的是对一些backbone框架的方法的讲解.这几天重新看了几遍backbone的源码,才发现之前对于它的理解不够深入,只关注了它的一些部分的细节和 ...
- PHP 高级编程(3/5) - 使用SPL(标准PHP库)实现观察者模式
SPL(标准PHP库 - Standard PHP Library)是PHP5面向对象功能中重要的部分.原文解释是这样的“The Standard PHP Library (SPL) is a col ...
- 设计模式--观察者模式初探和java Observable模式
初步认识观察者模式 观察者模式又称为发布/订阅(Publish/Subscribe)模式,因此我们可以用报纸期刊的订阅来形象的说明: 报社方负责出版报纸. 你订阅了该报社的报纸,那么只要报社发布了新报 ...
- 学C#之设计模式系列笔记(2)观察者模式
一.借鉴说明 1.<Head First Design Patterns>(中文名<深入浅出设计模式>) 2.维基百科,观察者模式,https://zh.wikipedia.o ...
- PHP 观察者模式
观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. [观察者模式中主要角色] 1.抽象主题(Subject)角色: 抽象主题提供了增加 ...
- GJM: 设计模式 - 观察者模式
GJM : 观察者模式 视频地址: http://www.imooc.com/learn/415 本课程通过一个天气预报的发布和订阅案例,来讲解观察者模式在Java项目中的应用.主要包括观察者模式的结 ...
随机推荐
- socket应用的例子
当使用 C 语言实现 Socket 编程时,可以通过系统提供的网络库来实现网络通信.以下是一个简单的示例,演示了如何创建一个简单的服务器和客户端,实现客户端向服务器发送消息并接收回复的功能. 服务器端 ...
- 其它——windows提示缺少VCRUNTIME140.dll错误
文章目录 一 原因 二 解决方法一 三 解决方法二 缺少了Microsoft.Net.Framework的安装 一 原因 最新在系统安装一些软件发现提示 这是因为缺少了一下windows运行需要的库 ...
- pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simpleLooking in indexes: https://pypi.tuna.t ...
- mooc第四单元《管理团队》单元测试
第四单元<管理团队>单元测试 返回 本次得分为:6.00/10.00, 本次测试的提交时间为:2020-08-30, 如果你认为本次测试成绩不理想,你可以选择 再做一次 . 1 判断(2分 ...
- 【IOC,AOP】spring的基础概念
IOC 控制反转 对象的创建控制权转交给外部实体,就是控制反转.外部实体便是IOC容器.其实就是以前创建java对象都是我们new一下,现在我们可以把这个new交给IOC容器来做,new出来的对象也会 ...
- 2023-10-14:用go语言,给定 pushed 和 popped 两个序列,每个序列中的 值都不重复, 只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时, 返回
2023-10-14:用go语言,给定 pushed 和 popped 两个序列,每个序列中的 值都不重复, 只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时, 返回 ...
- Java 深度优先搜索 and 广度优先搜索的算法原理和代码展示
111. 二叉树的最小深度 题目:给定一个二叉树,找出其最小深度.最小深度是从根节点到最近叶子节点的最短路径上的节点数量. 说明:叶子节点是指没有子节点的节点. 方法1:深度优先搜索 原理:深度优先搜 ...
- OTOCI 题解
OTOCI 题目大意 给定 \(n\) 个带权的点,需要进行四种操作:查询两点连通性:加边:修改点权:查询两点路径的权值和. 思路分析 首先观察题目,我们会发现,在所有的操作结束后,所有的点构成一个森 ...
- deepin解决文件管理器打不开和桌面黑屏的问题
总结 deepin 的优点是上手非常容易, 但截止当前(2021-6-24)的使用来说稳定性还不是非常好. 今天就遇到了无法显示桌面的问题,可以参照如下解决办法.只需使用红色框中的命令即可. 图片转载 ...
- APISIX proxy-cache 插件用法
APISIX 的 proxy-cache 插件可以对上游的查询进行缓存,这样就不需要上游的应用服务自己实现缓存了,或者也能少实现一部分缓存,通用的交给插件来做. 下面的操作都是基于 APISIX 3. ...