JavaRush /Java Blog /Random-TW /注入依賴項的簡單方法

注入依賴項的簡單方法

在 Random-TW 群組發布
依賴注入(DI)並不是一個容易理解的概念,將其應用到新的或現有的應用程式中更是令人困惑。Jess Smith向您展示如何使用 C# 和 Java 程式語言在沒有註入容器的情況下進行依賴項注入。 依賴注入的簡單方法 - 1在本文中,我將向您展示如何在 .NET 和 Java 應用程式中實現依賴項注入 (DI)。依賴注入的概念在 2000 年首次引起開發人員的注意,當時 Robert Martin 撰寫了文章「設計原則和模式」(後來以縮寫SOLID為人所知)。SOLID 中的 D 指的是反轉依賴(DOI),後來稱為依賴注入。最初也是最常見的定義:依賴倒置是基類管理依賴關係的方式的倒轉。Martin 的原始文章使用以下程式碼來說明類別Copy對較低層級類別的依賴關係WritePrinter
void Copy()
	{
	 int c;
	 while ((c = ReadKeyboard()) != EOF)
		WritePrinter(c);
	}
第一個明顯的問題是,如果更改方法的參數清單或類型WritePrinter,則需要在依賴方法的任何地方實現更新。此過程增加了維護成本,並且是新錯誤的潛在來源。
有興趣閱讀有關 Java 的內容嗎?加入Java 開發者小組!
另一個問題:Copy 類別不再是重複使用的潛在候選者。例如,如果您需要將從鍵盤輸入的字元輸出到檔案而不是印表機,該怎麼辦?為此,您可以Copy如下修改該類別(C++ 語言語法):
void Copy(outputDevice dev)
	{
	int c;
	while ((c = ReadKeyboard()) != EOF)
		if (dev == printer)
			WritePrinter(c);
		else
			WriteDisk(c);
	}
儘管引入了新的依賴項WriteDisk,情況並沒有改善(反而變得更糟),因為違反了另一個原則:「軟體實體,即類別、模組、函數等,應該對擴展開放,但對擴展關閉」。修改。” Martin 解釋說,這些新的條件 if/else 語句降低了程式碼的穩定性和靈活性。解決方案是反轉依賴關係,使寫入和讀取方法依賴Copy. 它們不是“彈出”依賴項,而是透過建構函數傳遞。修改後的程式碼如下所示:
class Reader
	{
		public:
		virtual int Read() = 0;
	};
	class Writer
	{
		public:
		virtual void Write(char) = 0;
	};
	void Copy(Reader& r, Writer& w)
	{
		int c;
		while((c=r.Read()) != EOF)
		w.Write(c);
	}
現在, 該類別Copy可以透過類別方法的不同實作輕鬆地重複使用ReaderWriter該類別Copy沒有有關類型Reader和的內部結構的任何信息Writer,因此可以在不同的實作中重複使用它們。但如果這一切對您來說似乎是某種官樣文章,也許下面的 Java 和 C# 範例會澄清這種情況。

Java 和 C# 範例

為了說明無需依賴項容器即可輕鬆進行依賴項注入,我們從一個簡單的範例開始,DI只需幾個步驟即可自訂該範例以供使用。假設我們有一個類HtmlUserPresentation,當呼叫它的方法時,會產生一個 HTML 使用者介面。這是一個簡單的例子:
HtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
任何使用此類程式碼的專案都會對該類別產生依賴HtmlUserPresentation,從而導致上述可用性和可維護性問題。一項改進立即顯現出來:建立一個帶有類別中目前可用的所有方法的簽名的介面HtmlUserPresentation。以下是該介面的範例:
public interface IHtmlUserPresentation {
	String createTable(ArrayList rowVals, String caption);
	String createTableRow(String tableCol);
	// Оставшиеся сигнатуры
}
建立介面後,我們修改類別HtmlUserPresentation以使用它。返回實例化 type HtmlUserPresentation,我們現在可以使用介面類型而不是基本類型:
IHtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
建立介面使我們能夠輕鬆使用IHtmlUserPresentation. 例如,如果我們想測試這種類型,我們可以輕鬆地將基本類型替換HtmlUserPresentation為另一種名為 的類型HtmlUserPresentationTest。到目前為止所做的更改使程式碼更易於測試、維護和擴展,但對重用沒有任何作用,因為HtmlUserPresentation使用該類型的所有類別仍然知道它的存在。若要刪除這種直接依賴關係,您可以將介面類型傳遞IHtmlUserPresentation給將使用它的類別或方法的建構子(或方法參數清單):
public UploadFile(IHtmlUserPresentation htmlUserPresentation)
建構函式UploadFile現在可以存取該類型的所有功能IHtmlUserPresentation,但對實作該介面的類別的內部結構一無所知。在此上下文中,類型注入在建立類別的實例時發生UploadFileIHtmlUserPresentation透過將不同的實作傳遞給需要不同功能的不同類別或方法, 介面類型變得可重複使用。

結論和鞏固材料的建議

您了解了依賴注入,並且當其中一個類別實例化另一個類別以存取目標類型的功能時,類別稱為直接相互依賴。要解耦兩種類型之間的直接依賴關係,您應該建立一個介面。介面使類型能夠根據所需功能的上下文包含不同的實作。透過將介面類型傳遞給類別建構函式或方法,需要該功能的類別/方法不知道有關實現該介面的類型的任何詳細資訊。因此,介面類型可以在需要相似但不相同行為的不同類別之間重複使用。
  • 若要試驗依賴項注入,請查看一個或多個應用程式中的程式碼,並嘗試將頻繁使用的基本類型轉換為介面。

  • 變更直接實例化此基底類型的類別以使用此新介面類型,並將其傳遞到將使用它的類別方法的建構函式或參數清單。

  • 建立一個測試實作來測試此介面類型。一旦你的程式碼被重構,DI它將變得更容易實現,並且你會注意到你的應用程式在重複使用性和可維護性方面變得更加靈活。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION