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

收益:

  • 降低模块耦合度
  • 提升可维护性和可测试性
  • 统一通知流程,减少重复代码
相关推荐
geovindu1 小时前
go: Visitor Pattern
开发语言·设计模式·golang·访问者模式
小短腿的代码世界9 小时前
Qt文件系统与IO深度解析:从QFile到异步文件操作
开发语言·qt
徐某人..11 小时前
基于i.MX6ULL平台的智能网关系统开发
arm开发·c++·单片机·qt·物联网·学习·arm
(Charon)13 小时前
【C++/Qt】Qt 封装 TCP 客户端底层 Network 类:连接、收发、自动测试与错误处理
服务器·网络·qt·tcp/ip
ximu_polaris15 小时前
设计模式(C++)-行为型模式-模版方法模式
c++·设计模式
A-Jie-Y15 小时前
JAVA设计模式-抽象工厂模式
java·设计模式
故事还在继续吗16 小时前
设计模式完全指南
设计模式
小短腿的代码世界16 小时前
QCefView深度解析:Qt应用中嵌入Chromium浏览器的终极方案
开发语言·qt
薛定谔的悦17 小时前
共享数据总线(DPR)设计模式——嵌入式系统的“内存数据库”
jvm·数据库·设计模式