下面經過兩張簡單的圖,瞭解一下控制反轉的思想,咱們假設本身如今想吃回鍋肉!編程
首先,咱們能夠本身炒一道符合本身口味的回鍋肉,能夠多加肉!而後咱們就把它吃掉!!這種狀況下回鍋肉炒成什麼樣由咱們本身控制。網絡
ok!次日咱們又想吃回鍋肉了,可是有點懶,咱們選擇點外賣。單元測試
這回咱們叫的外賣,那麼商家將回鍋肉炒成什麼樣並非咱們能決定的,也就是回鍋肉炒成什麼樣不是咱們可以控制的,咱們就是拿到外賣吃。測試
很明顯回鍋肉的控制權從本身變成了別人,這種就叫作控制反轉。code
在面向對象編程中,每當咱們要new一個新的對象的時候,也就是咱們所說的實例化對象,通常狀況下都是主動new一個新的對象。在IOC思想中,咱們一般把實例化的任務交給別人,也就是本身主動的實例化變爲被動的實例化,本身對實例的控制權被別人替代了,即控制權反轉了。咱們通常將實例化的任務交給IOC容器統一管理生命週期。對象
依賴注入是實現控制反轉思想的一種方式,其想法就是在對象或屬性被初始化的時候,將它所須要的依賴從外部注入進來,並不須要本身內部實例化依賴。blog
咱們經過一段代碼(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的概念。string