DIP設(shè)計原則
- DIP 依賴倒置原則是一種軟件架構(gòu)設(shè)計的原則
- IoC控制反轉(zhuǎn)是一種反轉(zhuǎn)流庇配、依賴和接口的方式哗脖,是DIP的具體實現(xiàn)方式唬格。
- DI依賴注入是IoC控制反轉(zhuǎn)的一種實現(xiàn)方式龙誊,用來反轉(zhuǎn)依賴,是IoC控制反轉(zhuǎn)的具體實現(xiàn)方式春哨。
- IoC容器是依賴注入的框架荆隘,用來映射依賴、管理對象創(chuàng)建和生命周期赴背,也就是DI框架椰拒。
DIP依賴倒置原則用來轉(zhuǎn)換依賴,即高層模塊不依賴于低層模塊的實現(xiàn)凰荚,低層模塊依賴于高層模塊定義的接口燃观。傳統(tǒng)低層依賴高層實現(xiàn)很明顯的問題是當(dāng)再有低層添加接口的時候,需要重新去修改高層的實現(xiàn)便瑟。遵從依賴倒置原則的設(shè)計缆毁,在添加低層模塊實現(xiàn)時會讓實現(xiàn)去適配接口,無需再修改高層接口代碼胳徽。
IoC 控制反轉(zhuǎn)
IoC控制反轉(zhuǎn)是DIP依賴倒置原則的一種實現(xiàn)积锅,也就是設(shè)計模式。IoC控制反轉(zhuǎn)為相互依賴的組件提供抽象养盗,將依賴(低層模塊)對象的獲取交給第三方(系統(tǒng))來控制缚陷,因此依賴對象不在被依賴模塊的類中直接通過new來獲取。
簡單來說B類依賴A類往核,原來的思路是在B類中new A使用箫爷,現(xiàn)在為其解耦,不在B類中new A聂儒,而是在其他地方new A在傳給B供B使用虎锚。為什么要這樣做呢?因為A類可能隨時會進(jìn)行修改衩婚,如果在B類中直接new A那就還需要去修改B類窜护。
DI 依賴注入
DI依賴注入就是將new A的實例傳入B類的實現(xiàn)方案,具體可分為:
- 構(gòu)造函數(shù)注入
- 屬性注入
構(gòu)造函數(shù)注入是在B類的構(gòu)造函數(shù)中將A類的實例傳入非春,關(guān)鍵在于傳入的位置在B類的構(gòu)造函數(shù)中應(yīng)該如何定義柱徙,如果定義為某個具體的類,就犯了高層依賴于低層的錯誤奇昙。為了規(guī)避這種錯誤护侮,應(yīng)該讓高層依賴于抽象類,讓底層統(tǒng)一繼承這個抽象類储耐。
屬性注入是通過修改B類的屬性羊初,將A傳入B。實現(xiàn)方式與構(gòu)造函數(shù)注入類似什湘,都是中間依賴于一個抽象類长赞。
例如:在沒有IoC的年代里晦攒,Car汽車必須依賴Engine引擎和Wheel輪子才能跑起來,為了處理此種關(guān)系得哆,首先必須人為通過require將輪子和引擎引入勤家,然后通過new實例化,這樣汽車才能跑起來柳恐。
const Engine = require("/engine");
const Wheel = require("/wheel");
let Car = function(){
this.engine = new Engine();
this.wheel = new Wheel();
};
Car.prototype.run = function(){
this.engine.run();
this.wheel.run();
console.log("car run");
};
module.exports = Car;
這種做法存在的問題是使用require需要首先知道引擎和輪子的文件位置、文件名稱热幔、exports的對象乐设。一旦引擎的或輪子的文件名稱、所在位置绎巨、exports方式發(fā)生改變近尚,require操作必然會做出相應(yīng)的改變。由于汽車直接依賴于引擎和輪子场勤,如果做單元測試則會發(fā)現(xiàn)mock引擎或輪子是非常困難的戈锻,兩邊的代碼都需要修改。
例如:使用IoC之后進(jìn)行構(gòu)造函數(shù)注入
let Car = function(engine, wheel){
this.engine = engine;
this.wheel = wheel;
};
Car.prototype.run = function(){
this.engine.run();
this.wheel.run();
console.log("car run");
};
module.exports = Car;
此時Car無需知道Engine引擎和媳、輪子Wheel的具體位置格遭,由于不采用require的方式因此也無需知道引擎和輪子什么時候?qū)嵗哉{(diào)用run方法跑起來。這種方式去除了引擎和輪子的直接依賴留瞳,引擎和輪子無論叫做什么名字或位于哪里拒迅。重構(gòu)變得輕而易舉。相對汽車做單元測試時她倘,只需要依賴注入一個mock的引擎和輪子對象即可璧微,再也不用去修改引擎和輪子的代碼。
IoC容器
IoC控制反轉(zhuǎn)是解決組件間依賴關(guān)系硬梁、配置和生命周期的設(shè)計模式前硫,IoC因好萊塢名言“Don't call us, we'll call you”(別來叫我我會來叫你的)而被廣泛認(rèn)知。
IoC容器實際上就是一個DI依賴注入的框架荧止,用于簡化工作量屹电,可以將其視為更為高級的工廠。
IoC容器應(yīng)該提供的功能包括
- 動態(tài)創(chuàng)建罩息、注入依賴對象
- 管理對象生命周期
- 映射依賴關(guān)系