C++聚合类自动暴露特征类指定API的结构设计模式实现问题
问题解答
1. 自动暴露特征类指定API的实现方案
该需求可以实现,核心基于CRTP(奇异递归模板模式)实现接口自动转发,无需手动编写每个方法的转发逻辑。
每个特征类自行定义需要对外暴露的接口模板,通过静态类型转换获取聚合类实例,直接转发到内部特征成员。聚合类仅需要继承所有特征的接口模板,按需授予私有成员访问权限即可:
// 每个Feature自行定义需要对外暴露的接口模板 template <typename Derived> struct Feature1PublicApi { void OperationA() { return static_cast<Derived*>(this)->mF1.OperationA(); } int OperationC(int param) { return static_cast<Derived*>(this)->mF1.OperationC(param); } }; template <typename Derived> struct Feature2PublicApi { void OperationB() { return static_cast<Derived*>(this)->mF2.OperationB(); } };
聚合类实现:
struct Agg : Feature1PublicApi<Agg> , Feature2PublicApi<Agg> // 新增Feature仅需增加对应继承即可 { int MyMethod() { return 42; } // 给所有接口模板授予私有成员访问权限 template <typename T> friend struct Feature1PublicApi; template <typename T> friend struct Feature2PublicApi; private: Feature1 mF1; Feature2 mF2; // FeatureN mFN; };
使用方式完全符合预期:
Agg agg; agg.OperationA(); // 自动转发到mF1.OperationA() agg.OperationB(); // 自动转发到mF2.OperationB() agg.MyMethod(); // 聚合类自身方法不受影响
该方案兼容C++11及以上标准,新增特征、新增暴露方法仅需修改对应Feature的Api模板类,不需要调整Agg类的现有逻辑。
2. 通用Proxy Wrapper实现方案
可以实现通用代理,不需要为每个特征类单独编写完整代理类,核心思路是通过宏批量生成重复的转发逻辑,轻量实现如下:
#include <utility> // 通用方法转发宏,要暴露哪个方法直接调用宏生成即可 #define EXPOSE_METHOD(Class, MethodName) \ template <typename... Args> \ auto MethodName(Args&&... args) -> decltype((std::declval<Class&>().*&Class::MethodName)(std::forward<Args>(args)...)) { \ return (m_instance.*&Class::MethodName)(std::forward<Args>(args)...); \ } // 通用代理基类 template <typename T> class GenericProxy { public: explicit GenericProxy(T& instance) : m_instance(instance) {} protected: T& m_instance; };
每个特征的代理仅需要声明要暴露的方法,无需编写重复的转发逻辑:
// Feature1代理 struct Feature1Proxy : GenericProxy<Feature1> { using GenericProxy::GenericProxy; EXPOSE_METHOD(Feature1, OperationA) EXPOSE_METHOD(Feature1, OperationC) }; // Feature2代理 struct Feature2Proxy : GenericProxy<Feature2> { using GenericProxy::GenericProxy; EXPOSE_METHOD(Feature2, OperationB) };
聚合类的Get方法实现:
Feature1Proxy Agg::GetFeature1() { return Feature1Proxy(mF1); } Feature2Proxy Agg::GetFeature2() { return Feature2Proxy(mF2); }
如果使用C++20及以上标准,还可以结合静态反射实现完全无需手动定义代理类的方案,自动读取特征类声明的暴露方法列表生成代理。
内容的提问来源于stack exchange,提问作者Dess
相关产品推荐
相关产品推荐

