ITPub博客

首页 > 数据库 > 数据库开发技术 > 分布式软总线连接模块中观察者模式原理设计分析

分布式软总线连接模块中观察者模式原理设计分析

数据库开发技术 作者:二进制猎手 时间:2026-08-06 20:00:13 0 删除 编辑

概述

观察者模式(Observer Pattern)是分布式软总线连接模块的核心架构模式,它定义了一种一对多的依赖关系:当一个对象(被观察者/Subject)的状态发生改变时,所有依赖于它的对象(观察者/Observer)都会收到通知并自动更新。

在连接模块中,连接管理器(ConnManager)是被观察者,各业务模块(认证、通道、代理等)是观察者。这种设计使得连接状态的变化能够自动、透明地传播给所有关心的业务方,实现了松耦合的事件驱动架构。

一、观察者模式原理深度解析

1.1 模式定义与角色

观察者模式属于行为型设计模式,其经典结构包含四个角色:

角色英文职责
主题接口Subject定义注册、删除、通知观察者的方法
具体主题ConcreteSubject维护观察者列表,状态变化时通知
观察者接口Observer定义接收通知的更新方法
具体观察者ConcreteObserver实现具体的响应逻辑

1.2 经典UML类图

1.3 核心机制

1.4 两种通知方式

方式特点适用场景
Push推送被动接收,Subject主动传递数据数据确定且需要立即处理
Pull拉取主动获取,Observer按需查询数据量大或需要选择性获取

二、连接模块观察者模式的具体实现

2.1 核心数据结构

2.1.1 观察者回调接口(ConnectCallback)

定义在 softbus_conn_interface.h:

这是观察者接口的定义,每个业务模块必须实现这四个回调函数来响应连接事件。

2.1.2 观察者节点(ConnListenerNode)

定义在 softbus_conn_manager.c:

每个节点代表一个已注册的业务观察者:

  • moduleId — 唯一标识该观察者(如 MODULE_AUTH_CHANNEL、MODULE_PROXY_CHANNEL)
  • callback — 该观察者提供的四个事件处理函数
2.1.3 被观察者全局容器

2.2 注册与注销机制

2.2.1 注册观察者(AddListener)

关键设计点:

  • ✅ 互斥锁保护 — 多线程环境下安全注册
  • ✅ 去重机制 — 同一模块ID只允许注册一次
  • ✅ 动态内存分配 — 支持运行时增删观察者
2.2.2 注销观察者(DelListener)
2.2.3 对外接口

2.3 事件通知机制(核心分发逻辑)

连接管理器实现了四种不同粒度的事件通知:

2.3.1 广播式通知(连接建立/断开)

场景:连接建立或断开时,所有业务模块都需要知道

特点:

  • 📡 一对多广播 — 一个事件通知所有观察者
  • 🔄 无差别通知 — 所有观察者都收到相同的信息
  • 📦 快照拷贝 — 先复制链表再遍历,减少锁持有时间
2.3.2 选择性通知(数据接收)

场景:数据到达时,只有发送数据的源模块应该收到

特点:

  • 🎯 精确路由 — 按 moduleId 定位唯一目标观察者
  • 📊 数据解包 — 自动剥离协议头(ConnPktHead),只传递有效载荷
  • ⚡ 高效查找 — O(n)线性搜索,但实际观察者数量少(通常<20个)
2.3.3 可选通知(连接复用)

场景:连接复用时,部分模块可能不关心此事件

特点:

  • 🔒 空指针保护 — 允许观察者不实现可选回调
  • 🎛️ 渐进式接口 — 核心回调必填,扩展回调可选

2.4 观察者管理辅助函数

2.5 初始化时的桥接设置

架构意义:

  • 各底层连接实现(BR/BLE/TCP)通过这个统一回调向上报告事件
  • 连接管理器作为中介者,将事件分发给正确的业务观察者

2.6 完整的事件流转图

三、为什么采用这种观察者模式设计?

3.1 解决的核心问题

问题1:多对多的复杂依赖关系

没有观察者模式时的问题:

使用观察者模式后:

✅ 将 N×M 的网状依赖简化为 N+M 的星形依赖

问题2:连接状态的实时同步需求

分布式软总线的多个子系统需要实时感知连接状态变化:

  • 认证模块:连接建立后启动认证流程
  • 通道模块:连接可用后创建通道
  • 代理模块:连接变化时调整代理策略
  • P2P模块:WiFi Direct连接状态监控

如果采用轮询方式,会导致:

  • ❌ 延迟高(轮询间隔限制)
  • ❌ 浪费CPU资源(无效轮询)
  • ❌ 实现复杂(各模块自行维护定时器)

观察者模式实现即时推送,完美解决此问题。

3.2 设计优势分析

优势1:松耦合(Loose Coupling)

耦合程度对比:

维度直接调用观察者模式
编译期依赖强(需include头文件)弱(只需函数指针)
运行期依赖硬编码动态绑定
修改影响范围大(改一处可能影响多处)小(新增观察者无需改动被观察者)
优势2:开放封闭原则(OCP)

开放:对扩展开放 — 新增业务模块只需:

封闭:对修改封闭 — 新增观察者不需要修改连接管理器的任何代码!

优势3:单一职责原则(SRP)

各组件职责清晰分离:

组件职责
BR/BLE/TCP模块只负责底层连接的建立、维护、断开
连接管理器只负责事件收集和分发
业务模块只负责自身业务逻辑
优势4:动态可配置性

观察者可以在运行时动态注册和注销:

3.3 设计权衡与取舍

权衡1:性能开销
开销项影响缓解措施
函数指针间接调用微小延迟C语言函数指针开销极小
链表遍历查找O(n)时间复杂度观察者数量有限(<20),可忽略
内存拷贝快照少量内存分配快照只在事件发生时创建
互斥锁竞争可能阻塞锁持有时间极短(微秒级)

结论:对于连接事件的频率(秒级),这些开销完全可接受。

权衡2:调试难度增加

问题:间接调用导致调用栈不够直观

缓解措施:

  • 日志记录每次回调调用(CONN_LOGI)
  • DFX打点追踪事件传播路径
  • HiDump工具支持查看当前注册的观察者列表
权衡3:内存管理复杂性

问题:动态分配的观察者节点需要正确释放

缓解措施:

  • ConnServerDeinit() 时清理所有观察者
  • DelListener() 时释放单个节点
  • 使用 SoftBusFree() 统一内存管理

3.4 与其他模式的协同

连接模块实际上融合了多种设计模式:

3.5 为什么选择这种特定实现方式?

选择1:为什么用C语言函数指针而非虚函数?

原因:

  • 分布式软总线是系统级基础服务,要求高性能和可控性
  • C语言的函数指针比C++虚函数更轻量(无vtable间接寻址)
  • 避免ABI兼容性问题(C++虚函数在不同编译器下可能有差异)
  • 符合OpenHarmony内核态代码规范
选择2:为什么用链表而非数组存储观察者?

原因:

  • 动态扩容:观察者数量不确定,链表更灵活
  • 插入删除效率高:O(1)时间复杂度
  • 符合内核编程习惯:Linux内核大量使用 list_head 结构
选择3:为什么数据接收用精确投递而非广播?

原因:

  • 安全性:防止跨模块数据泄露(每个模块只收到发给自己的数据)
  • 效率:避免无关模块处理不属于自己的数据
  • 语义清晰:数据是有明确目标的,不是公共事件

总结:观察者模式设计的精髓

架构价值总结

分布式软总线连接模块的观察者模式设计体现了以下架构哲学:

设计维度体现
关注点分离连接管理与业务逻辑彻底解耦
可扩展性新增连接类型/业务模块无需修改现有代码
可维护性各模块独立开发、测试、部署
健壮性线程安全的注册/注销/通知机制
性能平衡在灵活性和效率之间取得最优平衡

核心设计原则落地

这种设计使得分布式软总线能够在异构网络环境(WiFi/蓝牙/P2P)下,为多样化业务场景(认证/通道/代理/同步)提供稳定可靠的连接基础设施,真正做到了**"一次连接,处处感知"**的架构愿景。

原文作者:六bring个六;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2018-03-25

  • 博文量
    11
  • 访问量
    870