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

收益:

  • 降低模块耦合度
  • 提升可维护性和可测试性
  • 统一通知流程,减少重复代码
相关推荐
therese_100861 天前
客户端架构:为什么、什么时候、怎么做
设计模式·安卓·鸿蒙
多加点辣也没关系1 天前
设计模式-解释器模式
设计模式·解释器模式
charlie1145141911 天前
现代Qt开发教程(新手篇)2.3——QImage、QPixmap、QIcon 图像处理基础
开发语言·图像处理·qt
Asurplus1 天前
23中设计模式
设计模式·创建型·结构型·行为型
geovindu1 天前
go: Semaphore Pattern
开发语言·后端·设计模式·golang·企业级信号量模式
AoDeLuo2 天前
SOEM2.0编译与Qt调用
qt·机器视觉
大树学长2 天前
【QT开发】Windows 10 + Qt 5.15.2 手动编译安装 Qt OPC UA 模块完整记录
开发语言·windows·qt
小短腿的代码世界2 天前
Qt低级网络编程与零拷贝技术在高频交易中的应用:从QTcpSocket到共享内存的全链路优化
开发语言·网络·qt
写了20年代码的老程序员2 天前
写了 20 年 Java,我发现 90% 的 if-null 和 try-catch 其实是因为缺了一条原则
设计模式·ai编程
qq_401700412 天前
Qt 自定义无边框窗口:标题栏、拖拽移动与缩放
开发语言·qt