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

普通架构:

复制代码
模块直接打电话

事件架构:

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

相关推荐
霸道流氓气质3 分钟前
Saga模式入门与实战:编排与协同模式、补偿设计原则与Java生产级实现
java·开发语言
Lhan.zzZ8 分钟前
Linux + Qt/QML:解决 QtQuick.VirtualKeyboard.Plugins 模块加载失败与环境变量配置
linux·数据库·qt
池佳齐17 分钟前
【软考高级架构师案例】SaaS 多租户架构,数据隔离选“一户一库”还是“共享表”?
架构
silvamux_26 分钟前
OpenAI Python SDK v1 迁移实战
开发语言·python
旋生万物26 分钟前
螺旋数不是玄学:Python 实现广义复数与等角螺线
开发语言·人工智能·python·云原生·aigc·软件工程·后端开发
半杯咖啡半行码27 分钟前
Linux字符设备驱动实战:ioctl接口与GPIO操作指南
linux·开发语言
ZoeLandia28 分钟前
TypeScript 07:工程化——import type、声明文件与 tsconfig
开发语言·前端·typescript
小小程序猴138 分钟前
用工程视角建模企业AI培训周期:三段账本估算器(Python实现)
开发语言·人工智能·python
javaDocker41 分钟前
授权、协议与提示注入:Personal Agent 的安全基线该抄哪几份作业
人工智能·安全·金融·架构
开开心心_Every1 小时前
文件查重软件批量删除重复文件释放空间
java·开发语言·c#·计算机外设·ocr·excel·perl