網(wǎng)站域名更換是怎么做的網(wǎng)站是怎么做出來的
C++那些事之依賴注入
最近星球里面有個小伙伴讓更新一下依賴注入,于是寫出了這篇文章,來從實際的例子講解,本文會講解一些原理與實現(xiàn),完整的實現(xiàn)代碼懶人版放在星球中,我們開始正文。
大綱:
直接依賴
接口依賴注入
模版依賴注入
依賴注入是一種常用的設計模式,通常會采用接口/模版的方式提高代碼的可測性與維護性,下面我們來舉個例子。
假設有一個用戶服務類UserService,需要通過HTTP客戶端與遠程服務器進行通信,在這種情況下我們可能會寫出如下三種實現(xiàn)。
1.直接依賴
UserService內(nèi)部直接依賴HttpClient,例如:
class?HttpClient?{public:std::string?Get(const?std::string&?url);void?Post(const?std::string&?url,?const?std::string&?data);
};class?UserService?{private:HttpClient?m_httpClient;
};
UserService內(nèi)部通常會有一些方法去操作m_httpClient,這種方式簡單粗暴,但是UserService與具體的HttpClient相耦合,導致難以替換依賴對象,也難以進行單元測試。
于是引出了后面兩個方法。
2.接口依賴注入
我們的目標是期望測試的時候很方便的測試,而不需要創(chuàng)建一個具體的類,可以由用戶mock出一個類去測試,那么我們可以想到接口,將HttpClient抽出來,得到:
struct?IHttpClient?{virtual?std::string?Get(const?std::string&?url)?=?0;virtual?void?Post(const?std::string&?url,?const?std::string&?data)?=?0;virtual?~IHttpClient()?=?default;
};
class?UserService?{private:std::unique_ptr<IHttpClient>?m_httpClient;
};
那么在測試的時候便可以mock出一個client進行測試,例如:
class?MockHttpClient?:?public?IHttpClient?{
public:MOCK_METHOD(std::string,?Get,?(const?std::string&?url),?(override));MOCK_METHOD(void,?Post,?(const?std::string&?url,?const?std::string&?data),?(override));
};auto?mockHttpClient?=?std::make_unique<MockHttpClient>();
UserService?userService(std::move(mockHttpClient));
經(jīng)過以上改造,我們可以做到:
在 .cc 文件中隱藏實現(xiàn)細節(jié)
針對抽象接口工作
在對象構造期間注入依賴項
3.模版依賴注入
模板依賴注入通過C++模板技術,將依賴對象作為模板參數(shù)傳遞給UserService
。在實例化模板時,指定具體的HTTP客戶端實現(xiàn)。這種方法在編譯時解決依賴問題,無需虛函數(shù)調用,提高了性能。同時,也使得UserService
類可以靈活地與不同的HTTP客戶端實現(xiàn)進行集成,并且易于進行單元測試。
template?<typename?THttpClient>
class?UserService?{private:THttpClient?m_httpClient;
};
在這種情況下比較好測試,例如:
UserService<MockHttpClient>?userService;
這種方式有如下好處:
在模板實例化期間注入依賴項
無需虛擬調用(注意 THttpClient 不是接口,因此可以在編譯時解析調用)
以上便是本節(jié)要講的所有內(nèi)容,本節(jié)完整代碼放于星球,歡迎訂閱下載!
跟我一起實踐寫代碼,戳這里呀~
往期推薦:
向量數(shù)據(jù)庫milvus源碼剖析之開篇
熱度更新,手把手實現(xiàn)工業(yè)級線程池