国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

對(duì)依賴倒置原則(DIP)及Ioc、DI、Ioc容器的一些理解

2019-11-14 21:02:27
字體:
供稿:網(wǎng)友
對(duì)依賴倒置原則(Dip)及Ioc、DI、Ioc容器的一些理解1、概述

所謂依賴倒置原則(Dependence Inversion PRinciple)就是要依賴于抽象,不要依賴于具體。簡(jiǎn)單的說就是要求對(duì)抽象進(jìn)行編程,不要對(duì)實(shí)現(xiàn)進(jìn)行編程,這樣就降低了客戶與實(shí)現(xiàn)模塊間的耦合,并由此引申出IoC、DI以及Ioc容器等概念。

2、意圖面向過程的開發(fā),上層調(diào)用下層,上層依賴于下層,當(dāng)下層劇烈變動(dòng)時(shí)上層也要跟著變動(dòng),這就會(huì)導(dǎo)致模塊的復(fù)用性降低而且大大提高了開發(fā)的成本。面向?qū)ο蟮拈_發(fā)很好的解決了這個(gè)問題,一般情況下抽象的變化概率很小,讓用戶程序依賴于抽象,實(shí)現(xiàn)的細(xì)節(jié)也依賴于抽象。即使實(shí)現(xiàn)細(xì)節(jié)不斷變動(dòng),只要抽象不變,客戶程序就不需要變化。這大大降低了客戶程序與實(shí)現(xiàn)細(xì)節(jié)的耦合度。3、正文

依賴倒置原則(DIP):一種軟件架構(gòu)設(shè)計(jì)的原則(抽象概念)。

控制反轉(zhuǎn)(IoC):一種反轉(zhuǎn)流、依賴和接口的方式(DIP的具體實(shí)現(xiàn)方式)。

依賴注入(DI):IoC的一種實(shí)現(xiàn)方式,用來反轉(zhuǎn)依賴(IoC的具體實(shí)現(xiàn)方式)。

IoC容器:依賴注入的框架,用來映射依賴,管理對(duì)象創(chuàng)建和生存周期(DI框架)。

一個(gè)一個(gè)來說吧,首先先來了解下"依賴倒置原則(DIP)":

舉個(gè)生活中的小例子:

取過錢的朋友都知道,只要我們手上有一張銀行卡,我們就可以到各個(gè)銀行的ATM機(jī)上去取款,在這個(gè)場(chǎng)景中ATM機(jī)器屬于高層模塊,我們手上的銀行卡屬于底層模塊。

在ATM機(jī)上提供了一個(gè)卡槽插口(接口),供各種銀行卡插入使用,在這里ATM機(jī)不依賴于具體的哪種銀行卡,它只規(guī)定了銀行卡的規(guī)格,只要我們手上的銀行卡滿足這個(gè)規(guī)格參數(shù),我們就可以使用它。

轉(zhuǎn)換下概念,也就是:

高層模塊不依賴于底層模塊,而底層模塊依賴于高層模塊的接口(高層模塊定義接口,底層模塊負(fù)責(zé)實(shí)現(xiàn))。

高層模塊(接口):抽象  底層模塊(實(shí)現(xiàn)接口):實(shí)現(xiàn) ==>兩者應(yīng)該依賴于抽象,抽象(高層)不依賴實(shí)現(xiàn)(底層),實(shí)現(xiàn)(底層)依賴于抽象(高層)。

再來舉個(gè)例子:

1、如果依賴不倒置將會(huì)出現(xiàn):高層模塊依賴于底層模塊,也就是說底層變成了抽象,高層需要實(shí)現(xiàn)抽象出來的所有接口,一旦底層出現(xiàn)新的模塊,則就需要去修改高層的模塊,破壞了開放-封閉原則。

2、如果依賴倒置將會(huì)出現(xiàn):底層模塊依賴于高層模塊,也就是說高層變成了抽象,底層只需要去實(shí)現(xiàn)高層的接口就行,一旦底層出現(xiàn)新的模塊,則高層模塊就不需要去修改(定義抽象接口不變)。

由此可見DIP的優(yōu)點(diǎn):

系統(tǒng)更柔韌:可以修改一部分代碼而不影響其他模塊。

系統(tǒng)更健壯:可以修改一部分代碼而不會(huì)讓系統(tǒng)崩潰。

系統(tǒng)更高效:組件松耦合,且可復(fù)用,提高開發(fā)效率。

接下來說下"控制反轉(zhuǎn)(Ioc)":

DIP是一種軟件設(shè)計(jì)原則,是告訴我們模塊之間應(yīng)該是怎樣的一種關(guān)系,那Ioc就是具體的一種軟件設(shè)計(jì)模式,告訴我們應(yīng)該如何去做,才能做到程序間的解耦。

Ioc(控制反轉(zhuǎn))為高、低層模塊之間提供了抽象,也就是第三方系統(tǒng),也就是依賴對(duì)象(底層對(duì)象)不在依賴的模塊中(高層模塊)中直接創(chuàng)建對(duì)象,而是把創(chuàng)建對(duì)象的權(quán)利交給第三次Ioc容器來創(chuàng)建,然后再把對(duì)象交給依賴模塊(聯(lián)想剛剛?cè)″X的例子,ATM機(jī)器是高層模塊,它自身并沒有決定要插入哪個(gè)銀行的銀行卡,比如建行,農(nóng)行,要插入什么卡的決定權(quán)在于我們(也就是第三方),我們插入什么行的卡,它就給我們什么銀行的服務(wù))。

來個(gè)具體代碼感受下Ioc的好處:(訂單系統(tǒng),底層操縱類是基于MySQL數(shù)據(jù)庫的)

MysqlHelper.java(數(shù)據(jù)庫操作類)

 1 package com.lcw.dip.test; 2  3 public class MysqlHelper { 4      5     public void add(){ 6         System.out.println("增加訂單.."); 7     } 8  9     public void delete(){10         System.out.println("刪除訂單..");11     }12     13     public void update(){14         System.out.println("修改訂單..");15     }16     17     public void find(){18         System.out.println("查詢訂單..");19     }20 }

Order.java(業(yè)務(wù)邏輯類)

 1 package com.lcw.dip.test; 2  3 public class Order { 4     private MysqlHelper helper = new MysqlHelper(); 5  6     public void addOrder() { 7         this.helper.add(); 8     } 9     10     public void delOrder(){11         this.helper.delete();12     }13     14     public void updateOrder(){15         this.helper.update();16     }17     18     public void FindOrder(){19         this.helper.find();20     }21 }

DipTest.java(測(cè)試類)

package com.lcw.dip.test;/** *DIP(Dependence Inversion Principle)依賴倒置原則 * @author Balla_兔子 * */public class DipTest {    public static void main(String[] args) {        Order order=new Order();        order.addOrder();    }}

看下操作效果:

Perfect,完美!!

但如果現(xiàn)在突然業(yè)務(wù)需求要改換成access數(shù)據(jù)庫,這時(shí)改怎么辦呢?

傳統(tǒng)的做法,我們需要再去編寫一個(gè)關(guān)于Access的數(shù)據(jù)庫操縱類,然后修改下Order類里的代碼,把實(shí)例化對(duì)象修改成Access類(new Access())。

那要是過幾天又要改成Oracle數(shù)據(jù)庫呢?

。。。。。反反復(fù)復(fù),周而復(fù)始,煩!

有沒有什么辦法可以解決這個(gè)繁瑣的問題呢?答案是必須有!不然我就不用打這么多字了~~

接下來依賴注入(DI)就派上用場(chǎng)了:

依賴注入是實(shí)現(xiàn)Ioc的一種重要方式,將依賴的對(duì)象的創(chuàng)建權(quán)交給外部(第三方)來處理,而不是在自身new出一個(gè)實(shí)例。

例如上面的添加訂單例子,我們?cè)趧?chuàng)建數(shù)據(jù)庫操縱對(duì)象的時(shí)候是在Order類中直接new出,這樣有個(gè)很不好的地方就是,一旦數(shù)據(jù)庫變動(dòng),則我們還要去修改Order類,很顯然這是不可取的,違反了開放-封閉原則 。

那我們應(yīng)該怎么做呢?答案很明顯就是利用DI(依賴注入),將創(chuàng)建對(duì)象的權(quán)利交給外部(第三方)實(shí)現(xiàn),然后再傳遞給需要調(diào)用對(duì)象的模塊,也就是高層模塊。

傳遞注入的方式有三種:

1、構(gòu)造注入:顧名思義利用構(gòu)造方法注入

2、setter方法注入:在需要注入的類里提供一個(gè)setter方法

3、接口注入:因?yàn)榫哂写a侵入性,一般很少用,前2種居多

說了這么多,上代碼直接看實(shí)例吧

DbHelper.java

 1 package com.lcw.dip.test; 2  3 public class DbHelper { 4      5     public void add(){ 6         System.out.println("增加訂單.."); 7     } 8  9     public void delete(){10         System.out.println("刪除訂單..");11     }12     13     public void update(){14         System.out.println("修改訂單..");15     }16     17     public void find(){18         System.out.println("查詢訂單..");19     }20 }

Order.java

 1 package com.lcw.dip.test; 2  3 public class Order { 4     //private MysqlHelper helper = new MysqlHelper(); 5     private DbHelper helper; 6     public Order(DbHelper helper){//提供構(gòu)造方法,注入屬性 7         this.helper=helper; 8     } 9 10     public void addOrder() {11         this.helper.add();12     }13     14     public void delOrder(){15         this.helper.delete();16     }17     18     public void updateOrder(){19         this.helper.update();20     }21     22     public void FindOrder(){23         this.helper.find();24     }25 }

DipTest.java

 1 package com.lcw.dip.test; 2  3 /** 4  *DIP(Dependence Inversion Principle)依賴倒置原則 5  * @author Balla_兔子 6  * 7  */ 8 public class DipTest { 9     public static void main(String[] args) {10         //Order order=new Order();11         DbHelper helper=new DbHelper();12         Order order=new Order(helper);//注入DbHelper對(duì)象13         order.addOrder();14     }15 16 }

效果依舊,這樣就很方便我們下次修改了,比如我們要換成Access數(shù)據(jù)庫,那么這次我們只需要去修改數(shù)據(jù)庫操縱類DbHelper就可以了,就不必要去動(dòng)Order類了。

再來看下利用setter方法的注入:

DbHelper.java 數(shù)據(jù)庫操作底層類不變

Order.java

 1 package com.lcw.dip.test; 2  3 public class Order { 4 //    private MysqlHelper helper = new MysqlHelper(); 5 //    private DbHelper helper; 6 //    public Order(DbHelper helper){//提供構(gòu)造方法,注入屬性 7 //        this.helper=helper; 8 //    } 9     10     private DbHelper helper;11     public void setHelper(DbHelper helper) {12         this.helper = helper;13     }14 15     public void addOrder() {16         this.helper.add();17     }18     19     public void delOrder(){20         this.helper.delete();21     }22     23     public void updateOrder(){24         this.helper.update();25     }26     27     public void FindOrder(){28         this.helper.find();29     }30 }

DipTest.java

 1 package com.lcw.dip.test; 2  3 /** 4  *DIP(Dependence Inversion Principle)依賴倒置原則 5  * @author Balla_兔子 6  * 7  */ 8 public class DipTest { 9     public static void main(String[] args) {10 //        Order order=new Order();11 //        DbHelper helper=new DbHelper();12 //        Order order=new Order(helper);//注入DbHelper對(duì)象13         DbHelper helper=new DbHelper();14         Order order=new Order();15         order.setHelper(helper);16         order.addOrder();17     }18 19 }

效果依舊:

最后來說下關(guān)于Ioc容器:

在上面的例子中,我們都是通過手動(dòng)的方式來創(chuàng)建依賴對(duì)象,然后在手動(dòng)傳遞給被依賴模塊(高層),但對(duì)于大型的項(xiàng)目來說,各個(gè)組件之間的依賴關(guān)系式非常復(fù)雜的,如果我們還是用手動(dòng)來創(chuàng)建依賴對(duì)象并且手動(dòng)注入是個(gè)相當(dāng)繁雜的一個(gè)工作,而且還容易出錯(cuò),甚至出現(xiàn)不可控狀態(tài)。

因此Ioc容器就這樣誕生了,也就是DI的一個(gè)框架,用來簡(jiǎn)化我們的操作,Ioc容器可以做到動(dòng)態(tài)創(chuàng)建、注入對(duì)象,對(duì)象的生命周期管理,映射依賴關(guān)系等。

Ioc容器有很多比如:PicoContainer,JBoss Microcontainer,Soto,Spring等。

總結(jié)一下:

DIP是軟件設(shè)計(jì)的一種思想,IoC則是基于DIP衍生出的一種軟件設(shè)計(jì)模式。

DI是IoC的具體實(shí)現(xiàn)方式之一,使用最為廣泛。

IoC容器是DI注入的框架,它管理著依賴項(xiàng)的生命周期以及映射關(guān)系。

作者:Balla_兔子出處:http://m.survivalescaperooms.com/lichenwei/本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。正在看本人博客的這位童鞋,我看你氣度不凡,談吐間隱隱有王者之氣,日后必有一番作為!旁邊有“推薦”二字,你就順手把它點(diǎn)了吧,相得準(zhǔn),我分文不收;相不準(zhǔn),你也好回來找我!


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 鲁山县| 田林县| 镇江市| 子洲县| 中阳县| 黄石市| 格尔木市| 梨树县| 阿拉善右旗| 新绛县| 都匀市| 甘德县| 达拉特旗| 沽源县| 石首市| 连州市| 乡城县| 察隅县| 和田县| 石柱| 育儿| 宕昌县| 泾川县| 汶川县| 通山县| 松阳县| 忻州市| 汕头市| 佳木斯市| 手游| 北海市| 台湾省| 通江县| 逊克县| 六枝特区| 清河县| 辽宁省| 遂川县| 云安县| 灯塔市| 潞西市|