QT软件开发设计模式-观察者模式

1. 背景与目标

在 Qt 桌面软件开发中,界面刷新、状态同步、定时更新等场景往往存在一对多通知关系。 本模块将项目中的观察者逻辑抽象为独立能力,目标是:

  • 解耦"事件发布者"和"界面更新者"
  • 提供可复用的注册/通知/解绑机制
  • 支持通知前后钩子,便于扩展业务流程
  • 支持互斥控件保护,适配寄存器同步类场景

2. 观察者模式在本模块中的落地

观察者模式核心思想是:

  1. Subject 维护观察者列表
  2. 状态变化时 Subject 主动通知所有观察者
  3. Observer 在回调中执行各自更新逻辑

本模块将这一过程封装为三个核心角色:

  • SubjectWidgetModule:通用发布者(注册/反注册/通知)
  • ObserverWidgetModule:通用观察者基类(绑定/解绑/更新入口)
  • SyncByRegSubjectModule:带互斥控件保护的发布者扩展

3. 模块结构

  • modules/observer_module/observer_module.h
  • modules/observer_module/observer_module.cpp
  • modules/observer_module/example_usage.cpp

4. 核心接口说明

4.1 SubjectWidgetModule

主要职责:

  • 维护观察者列表(线程安全)
  • 分配唯一观察者 ID
  • 执行通知流程

关键接口:

  • quint32 addObserver(QWidget *widget, ObserverCallback callback, void *context = nullptr)
  • bool removeObserver(quint32 observerId)
  • void clearObservers()
  • void notify()

设计要点:

  • notify() 内部先复制快照再遍历,避免回调中增删订阅导致遍历失效
  • 提供 onBeforeNotify() / onAfterNotify() 钩子,支持模板方法扩展

4.2 ObserverWidgetModule

主要职责:

  • 封装绑定和解绑生命周期
  • 向业务子类暴露统一更新入口 onUpdate()

关键接口:

  • bool bind(SubjectWidgetModule *subject, QWidget *widget)
  • void unbind()
  • virtual void onUpdate(QWidget *widget) = 0

设计要点:

  • 析构时自动 unbind(),降低资源泄漏和悬挂订阅风险
  • unbind() 幂等,可重复调用

4.3 SyncByRegSubjectModule

主要职责:

  • 在通知前后自动执行互斥控件控制

依赖接口:

  • IExclusiveWidgetController

行为:

  • 通知前调用 disableWidgets()
  • 通知后调用 enableWidgets()

5. 快速使用示例

复制代码
#include "modules/observer_module/observer_module.h"

using namespace observer_module;

class MyObserver : public ObserverWidgetModule {
protected:
    void onUpdate(QWidget *widget) override
    {
        Q_UNUSED(widget);
        // 在这里执行 UI 或模型更新
    }
};

void demo(QWidget *target)
{
    SubjectWidgetModule subject;
    MyObserver observer;

    observer.bind(&subject, target);
    subject.notify();
    observer.unbind();
}

6. 互斥控件场景示例

复制代码
#include "modules/observer_module/observer_module.h"

using namespace observer_module;

class MyExclusiveController : public IExclusiveWidgetController {
public:
    void disableWidgets() override
    {
        // 通知前禁用控件
    }

    void enableWidgets() override
    {
        // 通知后恢复控件
    }
};

void demoSync(QWidget *target)
{
    MyExclusiveController controller;
    SyncByRegSubjectModule subject(&controller);

    quint32 id = subject.addObserver(
        target,
        [](QWidget *widget, void *context) {
            Q_UNUSED(context);
            Q_UNUSED(widget);
            // 执行寄存器读取并刷新界面
        });

    subject.notify();
    subject.removeObserver(id);
}

7. 与原项目类映射关系

  • Subject_widget -> SubjectWidgetModule
  • Observer_widget -> ObserverWidgetModule
  • Subject_sync_ui_by_reg -> SyncByRegSubjectModule

8. 工程集成方式

将以下文件加入 .pro

复制代码
SOURCES += \
    modules/observer_module/observer_module.cpp

HEADERS += \
    modules/observer_module/observer_module.h

如需复用现有 Exclusive_widget_mgr,可增加一个适配器:

复制代码
class ExclusiveWidgetMgrAdapter : public observer_module::IExclusiveWidgetController {
public:
    explicit ExclusiveWidgetMgrAdapter(Exclusive_widget_mgr *mgr) : mgr_(mgr) {}

    void disableWidgets() override
    {
        if (mgr_) {
            mgr_->disable_exclusive_widgets();
        }
    }

    void enableWidgets() override
    {
        if (mgr_) {
            mgr_->enable_exclusive_widgets();
        }
    }

private:
    Exclusive_widget_mgr *mgr_ = nullptr;
};

9. 适用场景与收益

适用场景:

  • 多个控件同步同一数据源
  • 定时刷新 UI
  • 一处状态变化触发多处联动更新

收益:

  • 降低模块耦合度
  • 提升可维护性和可测试性
  • 统一通知流程,减少重复代码
相关推荐
秋田君6 分钟前
QT_网络编程体系
网络·arm开发·qt
Quz1 小时前
QML TextArea 实战(下):大文本加载与性能优化
qt
Quz1 小时前
QML TextArea 实战(中):Markdown 渲染与保持滚动
qt
C++ 老炮儿的技术栈16 小时前
基于Qt实现轻量化本地音乐播放器
开发语言·c++·qt·c·播放器·音乐
我不是疯子是傻子21 小时前
Qt 实时曲线卡顿优化:从QPainter到OpenGL的3级加速实战
开发语言·qt
秋田君1 天前
QT_XML文件操作
xml·数据库·qt
我不是疯子是傻子1 天前
串口通信数据帧粘包拆包再进化:基于 Qt 的滑动窗口与 CRC 校验实战
开发语言·qt
程序员老陆1 天前
Qt中实现窗口真全屏(覆盖Windows任务栏)
开发语言·windows·qt
workflower1 天前
例二:某汽车制造企业深度融合AI智能体,构建园区网络的智能运维体系
人工智能·机器学习·设计模式·机器人·云计算·汽车·制造
ly76891 天前
Java 设计模式详解:从原则到 23 种经典模式
java·开发语言·设计模式