0x00.前言
當(dāng)我們研究一些晦澀的源碼基跑,上網(wǎng)查閱資料的時候,映入眼簾的總有這么些名詞:DIP描焰、IOC媳否、DI、DL、IOC容器這些專業(yè)名詞篱竭。如果不懂這些名詞背后的含義力图,我們內(nèi)心有可能是這樣的:
image
0x01.小例子
/**
* 餐廳類
*/
public class Restaurant {
//后臺收銀系統(tǒng)
private WeChatPay pay = new WeChatPay();
//收款操作
public void transact(double money) {
pay.receiveMoney(money);
}
}
import java.util.Date;
/**
* 微信
*/
public class WeChatPay {
public void receiveMoney(double money) {
System.out.println(new Date() + ",已用微信收款:" + money + "元");
}
}
這時候Restaurant類就依賴于WeChatPay,兩個類產(chǎn)生依賴
0x02.DIP
DIP的英文名:Dependency Inversion Principle室抽,中文名:依賴倒轉(zhuǎn)原則
定義:
High-level modules should not depend on low-level modules. Both should depend on abstractions
Abstractions should not depend on details. Details should depend on abstractions
理解:
高層模塊不應(yīng)該直接依賴于底層模塊的具體實現(xiàn),而應(yīng)該依賴于底層的抽象靡努。換言之坪圾,模塊間的依賴是通過抽象發(fā)生,實現(xiàn)類之間的不發(fā)生直接依賴關(guān)系惑朦,其依賴關(guān)系是通過接口或抽象類產(chǎn)生的
面向接口編程
它僅僅是面向?qū)ο筌浖O(shè)計的一種原則兽泄。它僅僅告訴你兩個模塊之間如何協(xié)調(diào)依賴關(guān)系,但是并沒有告訴你如何做漾月!
舉個例子
我們經(jīng)常所說的三層架構(gòu)(UI病梢、BLL、DAL)
圖二的版本梁肿,就是高層模塊依賴于低層模塊的抽象蜓陌,就好像依賴“倒置”。這樣可以使得整體的架構(gòu)更加的穩(wěn)定吩蔑,靈活钮热,及自如的面對需求的變化。
0x03.IOC
- IOC的英文名:Inversion Of Control 烛芬,中文名:控制反轉(zhuǎn)
- IOC基于DIP原則上的實現(xiàn)的是一種軟件設(shè)計模式隧期,它告訴你應(yīng)該如何做,來解除相互依賴模塊的耦合赘娄。它為相互依賴的組件提供抽象仆潮,將依賴對象的獲得交給第三方來控制,即依賴對象不在被依賴的類中直接通過new來獲取遣臼。
- IOC的實現(xiàn)的方式一般有兩種性置,依賴注入和依賴查找。一般DI使用的比較多
0x04.DI
- DI的英文名:Dependency Injection揍堰,中文名稱:依賴注入蚌讼。
- DI就是將依賴對象的創(chuàng)建和綁定轉(zhuǎn)移到被依賴對象類的外部來實現(xiàn)。它提供是一種機制个榕,將需要依賴(低層模塊)對象的引用傳遞給被依賴(高層模塊)對象篡石。
DI注入有三種方式:
- 構(gòu)造函數(shù)注入
- 屬性注入
- 接口注入
Demo講解
/**
* di Ipay 接口
*/
public interface IPay {
void receiveMoney(double money);
}
/**
* 重構(gòu)后的微信支付
*/
public class WebChatPay implements IPay {
public void receiveMoney(double money) {
Date now = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(format.format(now) + ",已用重構(gòu)后的微信收款:" + money + "元");
}
}
/**
* 重構(gòu)后的餐廳類構(gòu)造器注入
*/
public class Restaurant {
private IPay _pay;
public Restaurant(IPay pay) {
this._pay = pay;
}
//收款操作
public void transact(double money) {
_pay.receiveMoney(money);
}
}
0x01.構(gòu)造器注入
System.out.println("==========通過構(gòu)造函數(shù)注入開始==============");
IPay pay = new WebChatPay();//在外部創(chuàng)建依賴對象
Restaurant restaurant = new Restaurant(pay);
restaurant.transact(10);
System.out.println("==========通過構(gòu)造函數(shù)注入結(jié)束==============");
這時候我們就看到Restaurant將依賴的WeChatPay對象的創(chuàng)建和綁定轉(zhuǎn)移到Restaurant類外部來實現(xiàn)了。這樣就解除了Restaurant類與WeChatPay類的耦合關(guān)系西采。如果將支付方式改成Alipay凰萨,只需要定義一個Alipay類,然后在外部重新綁定依賴。不需要修改Restaurant類胖眷。
0x02.屬性注入
System.out.println("==========通過屬性注入開始==============");
IPay paySetter = new WebChatPay();
RestaurantBySetter restaurantSetter = new RestaurantBySetter();
restaurantSetter.setPay(paySetter);
restaurantSetter.transact(10);
System.out.println("==========通過屬性注入結(jié)束==============");
0x03.接口注入
System.out.println("==========通過接口注入開始==============");
IPay payInterface = new WebChatPay();
RestaurantByInterface restaurantInterface = new RestaurantByInterface();
restaurantInterface.extraInstance(payInterface);
restaurantInterface.transact(10);
System.out.println("==========通過接口注入結(jié)束==============");
0x05.IOC容器
DI框架武通,用來自動創(chuàng)建、維護依賴對象珊搀,并管理其生命周期冶忱。
常使用的IOC容器有:
Net:Ninject、Spring.NET境析、Unity囚枪、Autofac等
Java:Spring等
0x06.總結(jié)
IOC帶來好處:
- 降低了各個組件之間的耦合性,增強了內(nèi)聚性劳淆。
- 大中型項目链沼,團隊分工明確,職責(zé)明確沛鸵,便于測試
- 使得模塊具有熱插拔特性括勺,增加了模塊的復(fù)用性