Subject/Observer模式下,基于纯虚基类的子类如何优雅生成多事件类型的Override Update方法
Subject/Observer模式下,基于纯虚基类的子类如何优雅生成多事件类型的Override Update方法
嗨,这个场景我太有共鸣了!当观察者类要同时监听N种事件,每个都得手动写一遍Update的override,不仅重复代码多,还容易漏写或者写错类型,用宏虽然能解决,但总觉得不够“优雅”。给你分享几个纯C++原生的优雅方案,完全不用依赖宏:
方案一:CRTP转发基类(兼容C++11及以上)
这是最常用也最兼容的方案,核心是用一个模板转发类,把observer<T>要求的Update调用,转发给我们自己的通用处理方法。
首先定义这个转发基类:
template <typename EventType, typename Derived> class ObserverForwarder : public observer<EventType> { public: void Update(const EventType& event) override { // 安全地转发给子类的通用处理方法 static_cast<Derived*>(this)->UpdateInternal(event); } };
然后我们的Manager类只需要继承对应事件类型的转发基类,再实现一次通用的UpdateInternal模板方法就行:
class Manager : public ObserverForwarder<eventA, Manager>, public ObserverForwarder<eventB, Manager> { public: // 通用的模板处理逻辑,只需要写一次 template <typename T> void UpdateInternal(const T& event) { // 这里写所有事件的通用处理逻辑,比如: std::cout << "处理事件: " << typeid(T).name() << std::endl; // 后续如果要加新事件,只需要在继承列表里加ObserverForwarder<NewEvent, Manager>就行 } };
这个方案的好处:
- 完全没有宏的预编译期问题,代码可读性拉满
- 类型安全,编译器会帮你检查所有继承的
observer<T>是否都有正确的Update实现 - 新增事件只需要修改继承列表,不用改其他逻辑,扩展性极强
方案二:C++17+ 用if constexpr 实现差异化处理
如果你的项目已经升级到C++17或以上,还能在通用的UpdateInternal里直接用if constexpr,给特定事件类型加专属逻辑,不用写额外的特化:
template <typename T> void UpdateInternal(const T& event) { // 通用逻辑 std::cout << "通用处理事件: " << typeid(T).name() << std::endl; // 针对eventA的专属逻辑,编译期就会确定分支 if constexpr (std::is_same_v<T, eventA>) { std::cout << "这是eventA的特殊处理" << std::endl; // 这里可以直接调用eventA的专属方法 } // 其他事件的专属逻辑同理 }
这种方式把所有逻辑都集中在一个方法里,不用分散到不同的特化函数里,代码更紧凑。
方案三:模板特化实现完全差异化的处理
如果某些事件的逻辑和通用逻辑差异极大,完全不想写在同一个方法里,还可以给UpdateInternal做模板特化:
// 通用模板(默认逻辑) template <typename T> void UpdateInternal(const T& event) { std::cout << "通用处理事件: " << typeid(T).name() << std::endl; } // 针对eventA的特化实现 template <> void UpdateInternal<eventA>(const eventA& event) { std::cout << "eventA专属处理逻辑" << std::endl; // 这里写eventA的完整专属代码 }
这种方式既保留了通用逻辑的复用,又能给特殊事件完全独立的实现,灵活性拉满。
以上这些方案都比宏的方式更优雅,完全符合C++的类型安全特性,也更容易维护和扩展。
备注:内容来源于stack exchange,提问作者alexbuisson
相关产品推荐
相关产品推荐

