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
  • 一处状态变化触发多处联动更新

收益:

  • 降低模块耦合度
  • 提升可维护性和可测试性
  • 统一通知流程,减少重复代码
相关推荐
Quz13 小时前
QML 基础按钮:Button、RoundButton 与 DelayButton
qt
Quz13 小时前
QML ToolTip 组件:图标、多行文本与阴影
qt
xcyxiner14 小时前
DicomViewer14(读取图像按固定窗宽窗位显示)
qt
第一个传播学17 小时前
忍者龙剑传4豪华版下载及其玩法解析
设计模式
马里马里奥-1 天前
从零搭建AI Agent工具链的技术文章大纲
开发语言·qt
Quz2 天前
QML 与 JavaScript 交互方式:内联函数、外部文件、信号槽与工作线程
javascript·qt
Quz2 天前
QML ToolTip 组件:延迟提示与自定义外观
qt
第一个传播学2 天前
赛博朋克2077修改器下载及其用法
设计模式
wWYy.2 天前
RPC详解
qt·rpc·php
Fu_Lin_2 天前
Qt嵌入式从零基础到精通(01):Qt嵌入式开发全景图:从桌面Qt到ARM Linux
linux·arm开发·qt·qt5·嵌入式linux