C++多层通信软件架构:LL层访问Mid层权限问题求解
解决方案:在保护用户层的同时让LL类访问中层
针对你的问题,核心是要在**不让用户直接碰中层CSlave_Com_Mid_level**的前提下,给底层LL类开合法的访问通道。这里有几个实用的解决方案,按推荐优先级排序:
方案1:封装中层访问接口+友元授权(最清晰易维护)
这个方案既不会暴露中层给用户,又明确了LL类的访问入口,避免直接友元的过度耦合:
首先修改高层CSlave_Com_API,添加一个仅LL类能调用的私有接口,用来返回中层实例的引用,同时给LL类加友元权限:
template<size_t user_data_length> class CSlave_Com_API: protected CSlave_Com_Mid_level<user_data_length> { // 仅授权LL类访问底层接口 friend class CSlave_Com_LL_Slave_Com; private: // 封装中层的访问入口,只有友元能调用 const CSlave_Com_Mid_level<user_data_length>& get_mid_level() const { return *this; // 因为本类是中层的protected子类,直接返回基类引用 } public: bool Process_Request(CRequest* const pRequest); private: bool Send_Answer(CRequest* const pRequest); bool Abort_Request(CRequest* const pRequest); };
然后调整LL类的构造函数,通过这个封装接口获取中层实例:
template<size_t message_length> class CSlave_Com_LL_Slave_Com { public: // 接收高层API实例,通过封装接口拿到中层引用 CSlave_Com_LL_Slave_Com(const CSlave_Com_API<message_length>& api_instance) : mid_level_instance(api_instance.get_mid_level()) {} ~CSlave_Com_LL_Slave_Com(); private: const CSlave_Com_Mid_level<message_length>& mid_level_instance; };
这样用户代码里只能看到CSlave_Com_API的public接口,完全碰不到中层;LL类则通过合法的封装接口访问中层,耦合性低,代码可读性也更好。
方案2:直接给LL类加友元(最简洁)
如果团队不介意友元的耦合性,这是最直接的方式:
在CSlave_Com_API里直接声明LL类为友元:
template<size_t user_data_length> class CSlave_Com_API: protected CSlave_Com_Mid_level<user_data_length> { friend class CSlave_Com_LL_Slave_Com; // 授权LL类访问protected基类 public: bool Process_Request(CRequest* const pRequest); private: bool Send_Answer(CRequest* const pRequest); bool Abort_Request(CRequest* const pRequest); };
然后LL类的构造函数可以通过静态转换直接从高层API实例拿到中层引用:
template<size_t message_length> class CSlave_Com_LL_Slave_Com { public: CSlave_Com_LL_Slave_Com(const CSlave_Com_API<message_length>& api_instance) : mid_level_instance(static_cast<const CSlave_Com_Mid_level<message_length>&>(api_instance)) {} ~CSlave_Com_LL_Slave_Com(); private: const CSlave_Com_Mid_level<message_length>& mid_level_instance; };
这个方案代码量最少,适合简单场景,但友元会增加类之间的耦合,后期维护如果要扩展LL类,需要注意友元权限的范围。
方案3:用组合替代protected继承(最彻底的封装)
如果你的高层API不需要继承中层的接口,只是把中层作为内部组件使用,可以把中层改成高层的私有成员,再通过友元让LL类访问:
修改高层API:
template<size_t user_data_length> class CSlave_Com_API { friend class CSlave_Com_LL_Slave_Com; private: // 把中层作为私有成员完全封装起来 CSlave_Com_Mid_level<user_data_length> mid_level; public: bool Process_Request(CRequest* const pRequest); private: bool Send_Answer(CRequest* const pRequest); bool Abort_Request(CRequest* const pRequest); };
LL类的构造函数直接访问高层的私有成员:
template<size_t message_length> class CSlave_Com_LL_Slave_Com { public: CSlave_Com_LL_Slave_Com(const CSlave_Com_API<message_length>& api_instance) : mid_level_instance(api_instance.mid_level) {} ~CSlave_Com_LL_Slave_Com(); private: const CSlave_Com_Mid_level<message_length>& mid_level_instance; };
这个方案完全隔离了中层和用户,用户甚至不知道中层的存在,符合最严格的封装原则,适合高层不需要复用中层接口的场景。
内容的提问来源于stack exchange,提问作者JuliusCaesar
相关产品推荐
相关产品推荐

