自研极简C++软交互事件系统:干掉观察者模式、碾压前端事件机制
前言
做C++开发久了,会发现一个痛点:传统事件机制、观察者模式、Qt信号槽、前端DOM事件,全都过度设计、暗坑超多、存在环境污染。
-
标准观察者模式:需要维护监听列表、注册/注销逻辑,代码臃肿,耦合隐性偏高;
-
前端浏览器事件:存在冒泡、捕获、默认行为、异步传染性、环境绑定,限制极大;
-
传统EventBus事件总线:依赖全局事件池,容易命名冲突、状态污染、内存堆积;
-
各类框架事件:绑定特定环境,无法通用,同步流程适配性极差。
为此,我从零自研了一套极简、无依赖、零污染、纯原生C++软交互事件系统 。摒弃所有冗余机制,直击事件交互最底层本质:目标观测 + 布尔规则判定 + 消息软交互。
没有冒泡、没有捕获、没有异步污染、没有全局冲突,全局定义也能完全隔离,适配所有C++场景,比传统事件架构、前端事件机制更干净、更强大、更灵活。
一、核心设计思想:重新定义「事件」
我们彻底跳出硬件/UI狭义事件(点击、鼠标移动、键盘触发)的桎梏,重新定义程序事件:
事件 = 程序内部任意时机、任意条件触发的状态交互行为
所有事件交互,底层永远只有两个核心:
-
观测目标:需要监控的变量、状态、数据对象
-
布尔规则:自定义触发条件,满足则触发正向事件,不满足则为反向状态
摒弃传统复杂的发布订阅、事件队列、监听容器,用最极简的逻辑实现跨函数、跨类、跨模块软通信。
核心架构二分设计(原创)
-
发射器(emiter):状态探针,只负责绑定观测对象、定义判定规则、生成状态消息(纯只读观测,无副作用)
-
接收器(acceptor) :消息转发中枢,只负责透传消息,不绑定任何业务逻辑,逻辑全权外放
二、关键原创巧思:! 状态标记机制
这是整套系统的点睛之笔,完美解决状态区分的所有工程坑点:
我们需要区分「条件满足/条件不满足」两种状态,但坚决不用:
-
❌ 固定哨兵值(none/default):容易和业务消息冲突
-
❌ 字符串截取:短字符串会出现截取前后无变化,无法区分状态
-
❌ 字符串翻转/加密:破坏语义、可读性极差
✅ 最优解:后缀添加 ! 符号
-
编程语义:! 代表取反,完美对应「条件不满足」的反向状态
-
视觉语义:感叹号醒目,一眼区分异常/正常状态
-
工程零坑:无论消息长短,原语义完整保留,两种状态永远不重合、无冲突
规则:
-
条件满足 → 返回原始消息(正向触发)
-
条件不满足 → 原消息 + !(反向常态)
三、完整封装:通用 EventBus.h 头文件
纯原生C++11及以上,无第三方依赖、无平台限制、可直接复用,支持任意类型变量观测。
cpp
#ifndef EVENTBUS_H
#define EVENTBUS_H
#include <string>
#include <functional>
namespace EventBus
{
// 通用事件发射器:绑定观测对象 + 自定义布尔规则 + 生成状态消息
template <typename T>
class emiter
{
private:
T& target; // 被观测的目标对象(引用绑定,实时监听)
bool conditionFlag = false; // 规则判定结果
std::string baseMsg; // 基础事件消息
public:
// 构造函数:绑定需要观测的变量/对象
emiter(T& obj) : target(obj) {}
// 设置基础事件消息
void setBaseMsg(const std::string& msg) {
baseMsg = msg;
}
// 自定义观测规则:传入布尔判定函数
void watch(std::function<bool(T&)> ruleFunc) {
conditionFlag = ruleFunc(target);
}
// 重载()运算符:根据规则返回不同状态消息
std::string operator()() {
// 满足条件:原消息 | 不满足:原消息+!(取反标记)
return conditionFlag ? baseMsg : baseMsg + "!";
}
};
// 通用事件接收器:纯转发、零内置逻辑、完全解耦
class acceptor
{
public:
// 双参数核心接口:消息体 + 自定义处理回调
void run(std::string msg, std::function<void(std::string)> handleFunc) {
// 仅转发消息,所有业务逻辑交由外部回调实现
handleFunc(msg);
}
};
}
#endif // EVENTBUS_H
四、实战演示:状态拦截与流程控制
我们实现一个经典场景:数值递增,达到阈值后自动拦截数值增长、触发超限逻辑,体现系统的流程控制能力。
cpp
#include <iostream>
#include "EventBus.h"
using namespace std;
// 全局定义:完全隔离、零污染
int num = 0;
EventBus::emiter<int> numEmitter(num);
EventBus::acceptor msgAcceptor;
void checkTask() {
// 1. 设置事件基础消息
numEmitter.setBaseMsg("overflow");
// 2. 自定义观测规则:数值大于等于5触发超限
numEmitter.watch([](int& val) {
return val >= 5;
});
// 3. 接收器转发消息,外部自定义业务逻辑
msgAcceptor.run(numEmitter(), [](string msg) {
if (msg == "overflow") {
// 条件满足:触发超限逻辑,拦截数值增长
cout << "[超限] 数值达标,停止递增n";
} else {
// 条件不满足:正常执行递增逻辑
num++;
cout << "[正常] 数值持续递增n";
}
});
cout << "当前数值:" << num << "n" << endl;
}
int main() {
// 循环执行,模拟持续监测
for (int i = 0; i < 6; i++) {
checkTask();
}
return 0;
}
运行结果
Plain
[正常] 数值持续递增
当前数值:1
[正常] 数值持续递增
当前数值:2
[正常] 数值持续递增
当前数值:3
[正常] 数值持续递增
当前数值:4
[超限] 数值达标,停止递增
当前数值:5
[超限] 数值达标,停止递增
当前数值:5
可以清晰看到:数值达到5后,自动拦截递增逻辑,实现了软事件的「状态监测+流程拦截」核心能力。
五、碾压传统事件机制的核心优势
1. 彻底摒弃所有冗余暗坑
对比前端DOM事件/传统EventBus:
-
❌ 无事件冒泡、无捕获、无默认行为
-
❌ 无异步传染性、无执行顺序混乱问题
-
❌ 无this指向异常、无闭包陷阱
-
❌ 无全局事件池污染、无命名冲突
2. 全局定义完全隔离,零污染
所有发射器独立绑定专属观测变量,接收器仅做消息转发,无共享状态、无相互干扰。哪怕定义上百个全局交互器,也不会出现任何冲突、状态污染。
3. 极致灵活,自定义任意事件
前端事件只有固定的点击、移动、滚动等预设事件,而本系统可以自定义任意业务事件:
-
数值超限事件
-
状态切换事件
-
数组满员事件
-
登录状态变更事件
-
自定义结构体状态异常事件
规则由你定,事件由你造,完全不受框架限制。
4. 架构彻底解耦,扩展性拉满
-
发射器:只观测、不修改、无副作用
-
接收器:只转发、无内置业务逻辑
-
业务逻辑:全部外放,按需自定义,可随时修改、替换
5. 同步场景完美适配,兼顾类异步体验
传统事件多依赖异步事件循环,本系统适配C++同步执行流程,可实现「定点安检式监测」,也可放入循环实现「探针式持续监听」,同步异步场景通吃。
六、对比传统观察者模式的降维打击
传统观察者模式:需要维护观察者列表、手动注册注销、存在内存泄漏风险、代码冗余,本质是框架封装后的固定模板。
本自研系统:剥离所有多余封装,直抵观察者模式核心本质------目标对象 + 布尔规则监测。用极简代码实现更强的能力,无冗余、无泄漏、无学习成本。
七、总结
这套自研C++极简软交互事件系统,重新定义了程序内部事件交互:
它没有前端事件的繁琐机制、没有传统事件总线的污染问题、没有观察者模式的臃肿冗余。
以极小代码量、极高灵活性、绝对隔离性、零暗坑,实现了:
-
跨模块软通信
-
实时状态监测
-
业务流程拦截
-
自定义事件驱动
是一套纯原生、通用、可落地、可商用的原创轻量级事件架构,适配控制台、桌面软件、游戏、嵌入式、服务端等所有C++开发场景。
原创不易,欢迎点赞收藏,后续持续迭代高阶功能:事件优先级、一次性监听、消息队列、多分区隔离!