Java架構直通車——徹底瞭解DIP、IOC與DI之間的關係

本來這個文章是面試準備:Spring/Spring MVC常見面試題彙總的一個小問題,但是覺得需要擴充的內容太多,就單獨寫成一個文章了。

DIP、IOC與DI之間的關係

在這裏插入圖片描述

DIP

原本的依賴是高層依賴於底層。假設我們設計一輛汽車:先設計輪子,然後根據輪子大小設計底盤,接着根據底盤設計車身,最後根據車身設計好整個汽車。這裏就出現了一個“依賴”關係:汽車依賴車身,車身依賴底盤,底盤依賴輪子。
在這裏插入圖片描述
這樣做的壞處是什麼呢? 可維護性很低 。假設設計完工之後,上司卻突然說根據市場需求的變動,要我們把車子的輪子設計都改大一碼。這下我們就蛋疼了:因爲我們是根據輪子的尺寸設計的底盤,輪子的尺寸一改,底盤的設計就得修改;同樣因爲我們是根據底盤設計的車身,那麼車身也得改,同理汽車設計也得改——整個設計幾乎都得改!

我們現在換一種思路:底層依賴於高層高層建築決定需要什麼,底層去實現這樣的需求。我們先設計汽車的大概樣子,然後根據汽車的樣子來設計車身,根據車身來設計底盤,最後根據底盤來設計輪子。這時候,依賴關係就倒置過來了:輪子依賴底盤, 底盤依賴車身, 車身依賴汽車。

實例參考

爲了理解DIP概念,我們還是用上面汽車的例子。只不過這次換成代碼。我們先定義四個Class,車,車身,底盤,輪胎。然後初始化這輛車,最後跑這輛車。代碼結構如下:
在這裏插入圖片描述

現在假設經理說要該輪胎的大小,把它的尺寸變成動態的,而不是一直都是30。我們需要這麼改:(牽一髮而動全身)

在這裏插入圖片描述

如果採用依賴倒置的方式是怎麼設計的呢?
在這裏插入圖片描述
這裏我們再把輪胎尺寸變成動態的,同樣爲了讓整個系統順利運行,我們需要做如下修改:

在這裏插入圖片描述
這裏我們是採用的構造函數傳入的方式進行的 依賴注入DI 。其實還有另外兩種方法:Setter傳遞接口傳遞

IOC

IoC,Inversion of Control(控制反轉)。

控制反轉(Inversion of Control) 就是依賴倒置原則的一種代碼設計的思路。把傳統上由程序代碼直接操控的對象的調用權交給容器,通過容器來實現對象組件的裝配和管理。這個控制權從從程序代碼本身轉移到了外部容器。

這樣對象與對象之間是松耦合、便於測試、功能可複用(減少對象的創建和內存消耗),使得程序的整個體系結構可維護性、靈活性、擴展性變高。
優點:

  1. 依賴注入把應用的代碼量降低。
  2. 它使應用容易測試,單元測試不再需要單例和JNDI查找機制。
  3. 最小的代價和最小的侵入性使鬆散耦合得以實現。
  4. IOC容器支持加載服務時的餓漢式初始化和懶加載。
  • spring 提供了三種主要的方式來配置 IoC 容器中的 bean
    基於 XML 文件配置
    基於註解配置
    基於註解 + java 代碼顯式配置、

實例參考

在這裏插入圖片描述
顯然你也應該觀察到了,因爲採用了依賴注入,在初始化的過程中就不可避免的會寫大量的new。這裏IoC容器就解決了這個問題。這個容器可以自動對你的代碼進行初始化,你只需要維護一個Configuration(可以是xml可以是一段代碼),而不用每次初始化一輛車都要親手去寫那一大段初始化的代碼。這是引入IoC Container的第一個好處。

IoC Container的第二個好處是:我們在創建實例的時候不需要了解其中的細節。在上面的例子中,我們自己手動創建一個車instance時候,是從底層往上層new的,這個過程中,我們需要了解整個Car/Framework/Bottom/Tire類構造函數是怎麼定義的,才能一步一步new/注入。
在這裏插入圖片描述
而IoC Container在進行這個工作的時候是反過來的,它先從最上層開始往下找依賴關係,到達最底層之後再往上一步一步new(有點像深度優先遍歷):
在這裏插入圖片描述
這裏IoC Container可以直接隱藏具體的創建實例的細節,在我們來看它就像一個工廠:
在這裏插入圖片描述

DI

DI依賴注入,是 IoC 實現的一種方式(還有一種是依賴查找)。通過依賴注入機制,簡單的配置即可注入需要的資源,完成自身的業務邏輯,不需要關心資源的出處和具體實現。

DI注入的方式:
spring支持setter注入和構造器注入,通常是由構造器注入來注入必須的依賴關係,對於可選的依賴關係,則setter注入是更好的選擇。setter注入需要類提供無參構造器或者無參的靜態工廠來創建對象。

面試總結:什麼是IOC?

IOC是依賴倒置原則的一種思路,他將由傳統代碼負責創建對象交由容器進行統一的裝配和管理,這就使得控制權從代碼本身轉移到了容器,這就是IOC的控制反轉。

而IOC的一種實現方式是依賴注入,前面說了IOC他是依賴倒置原則的思路,所以他的依賴關係是底層依賴於高層,底層是通過構造器注入或者setter注入到高層的,這就需要去關注底層的實現,而DI則爲我們屏蔽了這個過程,通過簡單的Configuration,無需去關注對象是怎麼一步步實現的,就可以拿到對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章