剖析DI

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 + "元");
    }
}

image
這時候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)

image

image

圖二的版本梁肿,就是高層模塊依賴于低層模塊的抽象蜓陌,就好像依賴“倒置”。這樣可以使得整體的架構(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é)束==============");
image

這時候我們就看到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é)束==============");
image

0x03.接口注入

System.out.println("==========通過接口注入開始==============");
IPay payInterface = new WebChatPay();
RestaurantByInterface restaurantInterface = new RestaurantByInterface();
restaurantInterface.extraInstance(payInterface);
restaurantInterface.transact(10);
System.out.println("==========通過接口注入結(jié)束==============");
image

0x05.IOC容器

DI框架武通,用來自動創(chuàng)建、維護依賴對象珊搀,并管理其生命周期冶忱。

常使用的IOC容器有:
Net:Ninject、Spring.NET境析、Unity囚枪、Autofac等
Java:Spring等

0x06.總結(jié)

IOC帶來好處:

  • 降低了各個組件之間的耦合性,增強了內(nèi)聚性劳淆。
  • 大中型項目链沼,團隊分工明確,職責(zé)明確沛鸵,便于測試
  • 使得模塊具有熱插拔特性括勺,增加了模塊的復(fù)用性
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市曲掰,隨后出現(xiàn)的幾起案子疾捍,更是在濱河造成了極大的恐慌,老刑警劉巖栏妖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拾氓,死亡現(xiàn)場離奇詭異,居然都是意外死亡底哥,警方通過查閱死者的電腦和手機咙鞍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來趾徽,“玉大人续滋,你說我怎么就攤上這事》跄蹋” “怎么了疲酌?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長了袁。 經(jīng)常有香客問我朗恳,道長,這世上最難降的妖魔是什么载绿? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任粥诫,我火速辦了婚禮,結(jié)果婚禮上崭庸,老公的妹妹穿的比我還像新娘怀浆。我一直安慰自己谊囚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布执赡。 她就那樣靜靜地躺著镰踏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沙合。 梳的紋絲不亂的頭發(fā)上奠伪,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機與錄音首懈,去河邊找鬼绊率。 笑死,一個胖子當(dāng)著我的面吹牛猜拾,可吹牛的內(nèi)容都是我干的即舌。 我是一名探鬼主播佣盒,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼挎袜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了肥惭?” 一聲冷哼從身側(cè)響起盯仪,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蜜葱,沒想到半個月后全景,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡牵囤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年爸黄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揭鳞。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡炕贵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出野崇,到底是詐尸還是另有隱情称开,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布乓梨,位于F島的核電站鳖轰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏扶镀。R本人自食惡果不足惜蕴侣,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望臭觉。 院中可真熱鬧睛蛛,春花似錦鹦马、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至客冈,卻和暖如春旭从,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背场仲。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工和悦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人渠缕。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓鸽素,卻偏偏與公主長得像,于是被迫代替她去往敵國和親亦鳞。 傳聞我的和親對象是個殘疾皇子馍忽,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容