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

收益:

  • 降低模块耦合度
  • 提升可维护性和可测试性
  • 统一通知流程,减少重复代码
相关推荐
Chasing__Dreams3 小时前
python--设计模式--13.1--结构性--享元模式
python·设计模式·享元模式
小温冲冲3 小时前
ReSharper 在 Visual Studio 中的详细配置指南
c++·ide·qt·visual studio
爱搞事的程小猿3 小时前
qt系统字体方案
c++·qt
彭于晏Yan3 小时前
Spring Boot中适配器模式的实现方式
spring boot·设计模式·适配器模式
C++ 老炮儿的技术栈3 小时前
C++、C#常用语法对比
c语言·开发语言·c++·qt·c#·visual studio
Ronin3053 小时前
【Qt常用控件】多元素控件
开发语言·qt·常用控件·多元素控件
※※冰馨※※4 小时前
【QT】System error #1455: 页面文件太小,无法完成操作
开发语言·windows·qt
奇树谦4 小时前
QMap 全面解析(Qt5 vs Qt6)
开发语言·qt
咯哦哦哦哦5 小时前
windows下VSCode配置C++/CMake/Qt/MVSC 开发环境 【电脑已经安装vs2022】
c++·vscode·qt