DIP 依賴反轉原則 Dependency Inversion Principle 的定義如下:
高階別的模組不應該依賴於低階別的模組, 他們都應該依賴於抽象.
假設Controller依賴於Repository的例項/實現, 而不是interface:
這個例子裡面Controller是高階別模組, Repository是低階別模組.
但是根據定義: 高階別的模組不應該依賴於低階別的模組, 他們都應該依賴於抽象. 那麼如何解決這個問題呢?
那就是 從Repository中提煉出一個interface, 叫做IRepository, 它就是個抽象:
這樣一來, Controller依賴於IRepository, 所以高階別模組不依賴於低階別模組, 他們現在都依賴於抽象了.
那麼這麼做有什麼好處? 為什麼要使用DIP原則?
答案就是: 減少變化帶來的影響.
看第一張圖:
就從一個方面來說, 如果Repository被重新編譯了, 那麼Controller肯定需要重新編譯, 也就是所有依賴於Repository的類都會被重新編譯.
而使用DIP原則之後:
我們可以在Repository裡面做出很多更改, 但是這些變化都不會影響到Controller, 因為Controller並不是依賴於這個實現.
只要IRepository這個interface或者叫Contract合約不發生變化, Controller就不會被影響到. 這也就可能會較少對整個專案的影響.
Interface 代表的是 "是什麼樣的", 而實現代表的是 "如何去實現".
Interface一旦完成後是很少改變的.
針對使用Repository+UnitOfWork模式的asp.net core的專案結構, 少許碼友可能會有一點錯誤的理解, 可能會把asp.net core專案的結構這樣劃分:
這樣一來, 其實就是這樣的:
高階別的包/模組依賴於低階別的包/模組.
也就違反了DIP原則, 所以如果想按原則執行, 就需要引進一個新的模組:
把所有的抽象相關的類都放在Core裡面.
這樣就滿足了DIP原則.
asp.net core的專案結構大致應該是這個思路:
由於Models是整個專案的核心內容, 所以也放在了Core裡面.
當然也可以分成多個專案去實現DIP, 但是不一定按多個專案分開了就一定實現了DIP, 還是要看他們之間的依賴關係.