對控制反轉和依賴注入的突然頓悟

aaayi發表於2021-06-24
控制反轉和依賴注入的概念在網路上有大量的解釋,很多都非常的詳細,但對我來說過多的解釋,容易把我繞來繞去,昨天聽大佬的課,突然清晰地頓悟了。希望通過簡單的描述,記錄我的理解。

控制反轉(IOC):

下面通過兩張簡單的圖,瞭解一下控制反轉的思想,我們假設自己現在想吃回鍋肉!

首先,我們可以自己炒一道符合自己口味的回鍋肉,可以多加肉!然後我們就把它吃掉!!這種情況下回鍋肉炒成什麼樣由我們自己控制

ok!第二天我們又想吃回鍋肉了,但是有點懶,我們選擇點外賣。

這回我們叫的外賣,那麼商家將回鍋肉炒成什麼樣並不是我們能決定的,也就是回鍋肉炒成什麼樣不是我們能夠控制的,我們就是拿到外賣吃。

很明顯回鍋肉的控制權從自己變成了別人,這種就叫做控制反轉。

在物件導向程式設計中,每當我們要new一個新的物件的時候,也就是我們所說的例項化物件,一般情況下都是主動new一個新的物件。在IOC思想中,我們通常把例項化的任務交給別人,也就是自己主動的例項化變為被動的例項化,自己對例項的控制權被別人替代了,即控制權反轉了。我們一般將例項化的任務交給IOC容器統一管理生命週期。

依賴注入(DI):

依賴注入是實現控制反轉思想的一種方式,其想法就是在物件或屬性被初始化的時候,將它所需要的依賴從外部注入進來,並不需要自己內部例項化依賴。

我們通過一段程式碼來看看為什麼注入的依賴符合控制反轉的思想。

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的概念。

相關文章