網(wǎng)站首頁(yè) 編程語言 正文
背景
最近遇到一個(gè)比較棘手的場(chǎng)景,我們有一堆模塊,他們有一個(gè)通用的基類,我們不防假設(shè)為 BaseClass,該類有一些通用的結(jié)構(gòu)以及需要重載的方法。這些模塊有一個(gè)堆同名但是不同類型
參數(shù)的方法,比如:
int DerivedClass1::DoNlpTask(const DerivedReq1& req, DerivedResp* resp);
類似這樣的。每個(gè) DerivedClass 的DoNlpTask都是同名不同參數(shù)的,而且這些要給業(yè)務(wù)去具體實(shí)現(xiàn)。正常來說,很容易想到函數(shù)重載的方式,但是很不幸,模板函數(shù)無法重載
但是,我們想讓框架層和業(yè)務(wù)層相對(duì)解耦,不想讓業(yè)務(wù)的具體類型等污染框架調(diào)度模塊的結(jié)構(gòu)。
解決方案
在這里,我們利用訪問者模式的思想,結(jié)合C++的模板來統(tǒng)一處理。先定義一個(gè)Visitor,該類定義好具體業(yè)務(wù)模塊的通用操作步驟;實(shí)現(xiàn)的時(shí)候利用模板特化來實(shí)例化不同的業(yè)務(wù)模塊及其DoNlpTask 函數(shù)。這樣在框架層只需要調(diào)用Visitor 的統(tǒng)一模板接口即可,具體參看一下代碼。
最終代碼
#include <iostream> #include <type_traits> // 以下模擬請(qǐng)求協(xié)議 ===================== class BaseReq {}; class DerivedReq : public BaseReq {}; class BaseResp {}; class DerivedResp : public BaseResp {}; DerivedReq g_derived_req; // 以下模擬 NLP ============================ class BaseClass { public: // 單純視為一個(gè)需要重載的函數(shù) virtual int get_field_id() = 0; virtual void WormUp () {} }; #define REGISTER_PROTOTYPE(req_type, resp_type) \ public: \ using ReqType = req_type; \ using RespType = resp_type; class DerivedClass : public BaseClass { // 注冊(cè)請(qǐng)求類型 REGISTER_PROTOTYPE(DerivedReq, DerivedResp) public: int DoNlpTask(const DerivedReq&, DerivedResp* resp) { std::cout << "Derived DoNlpTask\n"; } int get_field_id() override { return 1; } }; // 以下模擬pb反射 ========================= const BaseReq* GetReqType() { return &g_derived_req; } // 以下是 visitor 的定義 =========== class Visitor { public: template <typename ClassType> int DoVisit(ClassType* base) { static_assert(std::is_base_of<BaseClass, DerivedClass>::value, "type failed"); int idx = base->get_field_id(); std::cout << "visitor get field_id " << idx << std::endl; const auto* req = GetMessageType<typename ClassType::ReqType>(GetReqType()); typename ClassType::RespType resp; // 返回計(jì)算結(jié)果 return base->DoNlpTask(*req, &resp); } private: template <typename ReqType> const ReqType* GetMessageType(const BaseReq* req) { static_assert(std::is_base_of<BaseReq, ReqType>::value, "Message Type Error"); return static_cast<const ReqType*>(req); } }; int main() { DerivedClass dc; Visitor vis; vis.DoVisit(&dc); return 0; }
原文鏈接:https://juejin.cn/post/7044478763312087053
相關(guān)推薦
- 2023-07-22 spark啟動(dòng)參數(shù)性能優(yōu)化
- 2022-10-23 Python繪制牛奶凍曲線(高木曲線)案例_python
- 2023-04-06 C/C++程序鏈接與反匯編工具objdump的使用介紹_C 語言
- 2022-09-20 C#?Winform實(shí)現(xiàn)圓角無鋸齒按鈕_C#教程
- 2023-01-26 RecyclerView?源碼淺析測(cè)量?布局?繪制?預(yù)布局_Android
- 2022-10-11 React - 當(dāng)輸入框獲取焦點(diǎn)時(shí)自動(dòng)選中輸入框中的內(nèi)容
- 2022-08-15 spring5:創(chuàng)建spring項(xiàng)目并引入jar包
- 2023-02-27 python定時(shí)任務(wù)timeloop庫(kù)用法實(shí)例詳解_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支