QT 事件驱动架构

很多大型系统(工业软件、机器人系统、自动驾驶、复杂 Qt 应用)在规模变大以后,都会逐渐引入 事件驱动架构(Event Bus / Event Driven Architecture)

原因很简单:

当系统模块越来越多时,模块之间的调用关系会爆炸式增长,最终变得无法维护。

我用一个逐步演化的真实思维过程来解释。


一、最初阶段:直接调用(最直观)

系统刚开始只有几个模块:

  • UI
  • MotorController
  • CameraController

调用关系很简单:

复制代码
UI → MotorController
UI → CameraController

代码类似:

cpp 复制代码
void MainWindow::onStartClicked()
{
    motorController.start();
    cameraController.capture();
}

问题不大。


二、系统变大:调用关系开始爆炸

后来系统增加很多模块:

  • MotorController
  • CameraController
  • LightController
  • NetworkController
  • DataLogger
  • AlarmSystem
  • UI

此时如果还是直接调用,会变成:

复制代码
UI → MotorController
UI → CameraController
UI → LightController

MotorController → Logger
MotorController → Alarm

CameraController → Logger
CameraController → Network

Network → Controller

模块之间的关系变成一个 蜘蛛网结构

复制代码
 A → B
 A → C
 B → D
 C → D
 D → E
 E → B

这叫:

强耦合系统

问题:

1️⃣ 修改一个模块可能影响很多模块

2️⃣ 新增功能需要改很多代码

3️⃣ 很难理解系统结构


三、真实案例:增加一个"报警系统"

假设系统需要增加一个新模块:

复制代码
AlarmSystem

需求:

  • 电机过载报警
  • 温度过高报警
  • 网络断开报警

如果是直接调用:

MotorController 要加:

cpp 复制代码
if(overload)
    alarm.raise("motor overload");

CameraController:

cpp 复制代码
if(cameraError)
    alarm.raise("camera error");

NetworkController:

cpp 复制代码
if(disconnect)
    alarm.raise("network error");

问题:

❌ 每个模块都要修改

❌ 未来新增模块还要继续改

这就是 耦合地狱


四、工程师的思考:能不能让模块不互相认识?

工程师开始思考:

如果模块之间不直接调用,而是发布消息,会不会更好?

于是出现:

事件驱动架构


五、事件驱动架构的核心思想

模块之间不直接调用。

而是:

复制代码
发布事件

复制代码
订阅事件

通过一个 EventBus(事件总线) 连接。

结构变成:

复制代码
Module A → EventBus → Module B

模块之间 互相不知道对方存在


六、例子:电机完成运动

传统调用:

复制代码
MotorController → CameraController

代码:

cpp 复制代码
motorController.moveDone();

cameraController.capture();

问题:

MotorController 必须知道 CameraController。


事件驱动:

复制代码
MotorController → EventBus
CameraController ← EventBus

代码:

发布事件:

cpp 复制代码
eventBus.publish("MotorMoveDone");

订阅事件:

cpp 复制代码
eventBus.subscribe("MotorMoveDone",
    [](){
        camera.capture();
    });

MotorController 不知道 CameraController。


七、增加新功能时的变化

假设我们新增:

复制代码
Logger

记录电机完成事件。

传统方式:

需要修改:

复制代码
MotorController
CameraController

事件方式:

只需要:

复制代码
Logger 订阅事件

代码:

cpp 复制代码
eventBus.subscribe("MotorMoveDone",
    [](){
        logger.log("motor finished");
    });

原代码 完全不需要改


八、再举一个真实设备流程

自动检测设备流程:

复制代码
移动平台
→ 拍照
→ 图像检测
→ 上传结果

传统调用:

复制代码
MotionController
   ↓
CameraController
   ↓
InspectionController
   ↓
NetworkController

代码:

cpp 复制代码
motion.move();

camera.capture();

auto result = inspect.detect();

network.send(result);

模块互相依赖。


事件驱动:

复制代码
MotionController
   ↓
Event: MoveDone

CameraController
   ↓
Event: ImageCaptured

InspectionController
   ↓
Event: InspectionDone

结构:

复制代码
MotionController
      ↓
   EventBus
      ↓
CameraController
      ↓
   EventBus
      ↓
InspectionController

九、系统结构变化

没有 EventBus:

复制代码
A → B → C → D

有 EventBus:

复制代码
A → EventBus
B → EventBus
C → EventBus
D → EventBus

模块只依赖:

复制代码
EventBus

系统耦合大幅下降。


十、再举一个复杂例子(工业软件)

事件:

复制代码
TemperatureHigh

订阅者可能有:

复制代码
AlarmSystem
Logger
UI
CoolingController

发布者:

复制代码
SensorController

代码:

发布:

cpp 复制代码
eventBus.publish("TemperatureHigh");

订阅:

cpp 复制代码
eventBus.subscribe("TemperatureHigh",
    [](){ alarm.trigger(); });

eventBus.subscribe("TemperatureHigh",
    [](){ logger.log(); });

eventBus.subscribe("TemperatureHigh",
    [](){ ui.showWarning(); });

新增功能只需要:

复制代码
新增订阅者

十一、事件驱动带来的巨大好处

1 模块解耦

模块互相不认识。


2 可扩展

新增功能:

复制代码
新增订阅者

不用修改旧代码。


3 更符合现实世界

现实世界就是事件驱动:

复制代码
门打开 → 灯亮
门打开 → 摄像头启动
门打开 → 报警系统记录

4 易于并发

事件可以:

复制代码
异步处理
多线程处理

十二、Qt 为什么非常适合事件架构

Qt 本身就是 事件驱动框架

例如:

复制代码
Signal → Slot

本质就是:

复制代码
Event → Listener

例子:

cpp 复制代码
connect(button,
        &QPushButton::clicked,
        this,
        &MainWindow::onClicked);

这其实就是一个小型 EventBus。


十三、大型系统为什么几乎都用事件架构

因为系统规模一大,就会出现:

复制代码
模块数量 ↑
调用关系 ↑↑
复杂度 ↑↑↑

EventBus可以把:

复制代码
N² 的调用关系

变成:

复制代码
N 的关系

这是复杂度降低的关键


十四、一句话理解 EventBus

普通架构:

复制代码
模块直接打电话

事件架构:

复制代码
模块在广播电台发布消息
需要的人自己收听

相关推荐
2401_889884661 小时前
模板代码模块化设计
开发语言·c++·算法
qq_246100052 小时前
CSDN risk probe 1773588273
开发语言·javascript·ecmascript
2401_898075122 小时前
代码生成器优化策略
开发语言·c++·算法
Kim Jackson2 小时前
我的世界Java版1.21.4的Fabric模组开发教程(二十二)创建生物(上)实体外观与动画设计
java·开发语言·fabric
lsx2024062 小时前
Python 100例:编程实践与技巧解析
开发语言
大鹏说大话2 小时前
单点登录(SSO)全景指南:从原理剖析到落地实战
开发语言
逆境不可逃2 小时前
【从零入门23种设计模式21】行为型之空对象模式
java·开发语言·数据库·算法·设计模式·职场和发展
arvin_xiaoting2 小时前
三角协作架构:从问题发现到验证完成
架构·系统架构·llm·claude·ai agent·openclaw·多代理协作
健康平安的活着2 小时前
java中乐观锁+事务在批量导入,批量审批案例的使用
java·开发语言