当前位置: 首页 > news >正文

用Qt/C++玩转观察者模式:一个会聊天的设计模式

用Qt/C++玩转观察者模式:一个会聊天的设计模式

引言:你的代码需要一场高效对话

在软件开发中,你是否遇到过这样的场景?当用户点击登录按钮时,需要同时更新状态栏、刷新用户列表、记录操作日志…就像一群热情的朋友围着你,都在等着听你的最新消息。这时候,观察者模式就是你的最佳传声筒!

一、初识观察者模式:咖啡店的订阅服务

1.1 生活中的观察者

想象一家咖啡店的新品订阅服务:

  • 顾客(观察者)订阅新品通知
  • 咖啡店(被观察者)有新咖啡时自动通知所有订阅者
  • 顾客随时可以取消订阅

这不正是我们代码中需要的解耦之道吗?

1.2 模式结构解析

// 抽象主题(咖啡店)
class Subject {
public:virtual void attach(Observer* observer) = 0;virtual void detach(Observer* observer) = 0;virtual void notify() = 0;
};// 抽象观察者(顾客)
class Observer {
public:virtual void update(const QString& message) = 0;
};

二、Qt版实现:信号与槽的魔法

2.1 传统实现 vs Qt实现

传统方式需要手动维护观察者列表,而Qt的信号槽机制让这一切变得优雅:

传统方式Qt方式
手动管理观察者列表自动连接管理
显式调用notify()信号自动触发
容易内存泄漏父子对象自动释放

2.2 温度监测系统实战

假设我们要实现一个温度异常报警系统:

// 温度传感器(被观察者)
class TemperatureSensor : public QObject {Q_OBJECT
public:explicit TemperatureSensor(QObject* parent = nullptr) : QObject(parent) {}signals:void temperatureChanged(double temp);public slots:void checkTemperature() {double currentTemp = readHardware();emit temperatureChanged(currentTemp);}
};// 报警器(观察者)
class Alarm : public QObject {Q_OBJECT
public slots:void onTemperatureChanged(double temp) {if(temp > 38.0) {qDebug() << "【警报】温度异常:" << temp << "℃!";}}
};// 使用示例
TemperatureSensor sensor;
Alarm alarm;
QObject::connect(&sensor, &TemperatureSensor::temperatureChanged,&alarm, &Alarm::onTemperatureChanged);// 定时检测
QTimer timer;
timer.callOnTimeout([&sensor]{ sensor.checkTemperature(); });
timer.start(1000);

三、实战应用场景:那些年我们需要的观察时刻

3.1 UI更新三剑客

// 用户登录成功后
void onLoginSuccess() {emit userLoggedIn(userInfo); // 一个信号触发多个更新
}// 多个观察者自动响应:
// 1. 导航栏显示用户头像
// 2. 侧边栏加载用户权限菜单
// 3. 状态栏显示欢迎信息

3.2 配置热更新

当修改配置文件时:

connect(configManager, &ConfigManager::configUpdated,networkManager, &NetworkManager::reloadSettings);
connect(configManager, &ConfigManager::configUpdated,uiManager, &UIManager::applyTheme);

3.3 跨模块通信

订单模块和库存模块的解耦:

// 订单生成时
connect(orderSystem, &OrderSystem::newOrderCreated,inventorySystem, &InventorySystem::updateStock);
connect(orderSystem, &OrderSystem::newOrderCreated,financeSystem, &FinanceSystem::recordTransaction);

四、高级技巧:让你的观察更聪明

4.1 带参数的信号

// 带上下文信息的信号
void dataReceived(const QByteArray& data, const QDateTime& timestamp);// 观察者可以获取完整信息
connect(networkManager, &NetworkManager::dataReceived,dataProcessor, &DataProcessor::handleData);

4.2 连接类型选择

// 自动连接(默认)
Qt::AutoConnection// 队列连接(跨线程)
Qt::QueuedConnection// 阻塞连接(慎用!)
Qt::BlockingQueuedConnection

4.3 连接管理神器

// 安全连接(自动断开)
QMetaObject::Connection conn = connect(...);// 需要时断开
disconnect(conn);// 批量断开
disconnect(sender, nullptr, receiver, nullptr);

五、避坑指南:观察者的礼仪

  1. 避免信号风暴:高频信号使用防抖处理
// 使用定时器合并频繁更新
QTimer::singleShot(100, this, [this]{ emit dataUpdated(); });
  1. 注意生命周期:使用QPointer管理观察者
QPointer<Observer> weakObserver = observer;
connect(sender, &Sender::signal, weakObserver, [weakObserver]{if(weakObserver) weakObserver->handleUpdate();
});
  1. 预防循环触发:A触发B,B又触发A的情况

六、思考题:你身边有哪些观察者?

观察者模式其实无处不在:

  1. 股票价格变动通知
  2. 游戏中的成就系统
  3. 日志系统的多输出
  4. 设备的状态监控

试着用Qt的信号槽机制来实现这些场景吧!


后记:观察者模式就像代码世界的社交网络,让对象们优雅地保持联系。下次当你发现多个对象对同一事件感兴趣时,不妨说一句:“要不…我们connect一下?”

http://www.xdnf.cn/news/668827.html

相关文章:

  • 32.第二阶段x64游戏实战-封包-公共call
  • [Windows] 视频配音:Krillin AI v1.1.4
  • 【NLP基础知识系列课程-Tokenizer的前世今生第一课】Tokenizer 是什么?为什么重要?
  • Mac redis下载和安装
  • 【Docker】存储卷
  • 阿里云配置安全组策略开放端口
  • 阿里云CDN和腾讯云CDN综合对比
  • 飞牛fnNAS之手机访问篇
  • OpenSSH 服务配置与会话保活完全指南
  • 参数/非参数检验和连续/离散/分类等变量类型的关系
  • 好坏质检分类实战(异常数据检测、降维、KNN模型分类、混淆矩阵进行模型评估)
  • Ubuntu20.04系统安装,使用系统盘安装
  • 在thinkphp5.0中。单表使用 model clone 时就会有问题。 需要使用 alias(), 否则会报错。
  • 防腐防爆配电箱:采用 304 不锈钢材质,抗腐蚀、抗冲击,适应恶劣工况
  • 第三届黄河流域网安技能挑战赛复现
  • 2025吉林CCPC 题解(前六题)
  • [图文]图6.3会计事项-Fowler分析模式的剖析和实现
  • docker 搭建php 开发环境 添加扩展redis、swoole、xdebug(1)
  • Qt不同布局添加不同控件
  • 模型评价指标介绍
  • Spark、Hadoop对比
  • Excel 操作 转图片,转pdf等
  • Go语言中的浮点数类型详解
  • Kotlin 中 Lambda 表达式的语法结构及简化推导
  • 学习黑客 Metasploit 主要组件之Encoder
  • MS1826+MS2131 1080P@60Hz 4路输入输出USB3.0采集
  • 通过ansible playbook创建azure 资源
  • 解决ubuntu服务器未使用空间的分配
  • c++复习_第一天(引用+小众考点)
  • c#,vb.net使用OleDb写入Excel异常:字段太小而不能接受所要添加的数据的数量