控制反轉和依賴注入的概念在網絡上有大量的解釋,很多都非常的詳細,但對我來說過多的解釋,容易把我繞來繞去,昨天聽大佬的課,突然清晰地頓悟了。希望通過簡單的描述,記錄我的理解。
控制反轉(IOC):
下面通過兩張簡單的圖,了解一下控制反轉的思想,我們假設自己現在想吃回鍋肉!
首先,我們可以自己炒一道符合自己口味的回鍋肉,可以多加肉!然后我們就把它吃掉!!這種情況下回鍋肉炒成什么樣由我們自己控制。
ok!第二天我們又想吃回鍋肉了,但是有點懶,我們選擇點外賣。
這回我們叫的外賣,那么商家將回鍋肉炒成什么樣並不是我們能決定的,也就是回鍋肉炒成什么樣不是我們能夠控制的,我們就是拿到外賣吃。
很明顯回鍋肉的控制權從自己變成了別人,這種就叫做控制反轉。
在面向對象編程中,每當我們要new一個新的對象的時候,也就是我們所說的實例化對象,一般情況下都是主動new一個新的對象。在IOC思想中,我們通常把實例化的任務交給別人,也就是自己主動的實例化變為被動的實例化,自己對實例的控制權被別人替代了,即控制權反轉了。我們一般將實例化的任務交給IOC容器統一管理生命周期。
依賴注入(DI):
依賴注入是實現控制反轉思想的一種方式,其想法就是在對象或屬性被初始化的時候,將它所需要的依賴從外部注入進來,並不需要自己內部實例化依賴。
我們通過一段代碼(Go語言)來看看為什么注入的依賴符合控制反轉的思想。
type Player struct {
name string
}
type GameRoom struct {
player *Player
}
//這里我們就將GameRoom依賴的Player從外部注入進來
//Player的實例化也交給了外部,所以對於Player的控制權反轉了。
func NewGameRoom(player *Player) *GameRoom {
return &GameRoom{player: player}
}
很多情況下我們會使用接口注入,而接口的實例化就歸外部(通常是IOC容器),不僅符合多態,更加體現了依賴倒置原則(雙方都應該依賴一個抽象)。
type Player interface {
GetName() string
}
type GameRoom struct {
player Player
}
//Player通過接口的方式注入進來,我們無須
//關系Player如何實現的,這樣連注入的依賴
//也變成抽象的
func NewGameRoom(player Player) *GameRoom {
return &GameRoom{player: player}
}
這種方式好處頗多,比如更容易被單元測試、代碼耦合性降低等等等等。希望這篇最簡單的解釋,能夠使我們更快地理解IOC和DI的概念。