依賴倒置蝴光、控制反轉(zhuǎn)和依賴注入的區(qū)分
依賴倒置碌上、控制反轉(zhuǎn)和依賴注入的區(qū)分依賴倒置(Dependency Inversion Principle)凳谦、控制反轉(zhuǎn)(Inversion of Control)和依賴注入(Dependency Injection)從思想來講是統(tǒng)一的艘狭,或者說是類似的已卸,有人也說它們是同一個東西刻恭。但是還是可以做一點區(qū)分:
依賴倒置原則是進行軟件設(shè)計時考慮遵循的一個原則瞧省。具體為:
(1)上層模塊不應(yīng)該依賴于下層模塊,它們共同依賴于一個抽象鳍贾。
(2)抽象不能依賴于具象鞍匾,具象依賴于抽象。
控制反轉(zhuǎn)
是軟件運行時體現(xiàn)出來的一個特征:如果對象A運行時依賴于對象B贾漏,但A并不去創(chuàng)建B候学,而是從外界直接取得B。
也就是說纵散,一個對象并不是自己去創(chuàng)建它所依賴的其它對象梳码。
依賴注入是控制反轉(zhuǎn)的一種實現(xiàn)手段。
如上面的例子伍掀,B的取得并不需要A的干涉掰茶,而是利用某些框架在通過構(gòu)造參數(shù)或?qū)傩栽O(shè)置來實現(xiàn)。
IOC:Inversion of Control 控制反轉(zhuǎn)
DI:Dependency Injection 依賴注入
控制反轉(zhuǎn)蜜笤,從字面意思來看濒蒋,就是控制權(quán)又被動變主動,最后又變回被動把兔。
舉個例子:
你的主管要求你做一件事情沪伙,這個時候就存在這么幾個過程:
- 主管命令你做事情(這個時候主動權(quán)在主管,你是被動的)
- 你接到命令做事情(這個時候主題是你县好,你是主動的围橡,控制權(quán)在你手里)
- 你完成事情(這個時候主題依然是你,控制權(quán)在你手里)
- 報告主管做完事情(主動權(quán)又叫交到主管手里了)
上面的整個過程就完成了一次IOC缕贡,從上面可以看出翁授,IOC的基本思想是控制權(quán)的轉(zhuǎn)換過程拣播。
舉個代碼的例子:
假如有Class A,Class B收擦,在A內(nèi)部會初始化一個B贮配,調(diào)用B的一個方法DoMethod
public Class B{
public void DoMethod(){
//do somthing;
}
}
public Class A {
public void Excute() {
B b=newB()塞赂;
b.DoMethod()泪勒;
}
}
假如在Main函數(shù)中如下執(zhí)行:
A a=newA();
a.Excute();
從這兩行代碼來看,事實上也存在一個IOC的過程减途,a——>b——>a酣藻,理解的關(guān)鍵點就在在A的內(nèi)部調(diào)用Excute的時候,方法b.DoMethod的執(zhí)行鳍置。
理解了IOC辽剧,我們再看一下DI。
從上面A調(diào)用B我們可以看出税产,在初始化一個A的實例時怕轿,也必須實例化一個B,也就是說如果沒有B或者B出了問題辟拷,A就無法實例化撞羽,這就產(chǎn)生了一種依賴,就是A依賴B衫冻,這種依賴從設(shè)計的角度來說就是耦合诀紊,顯然它是無法滿足高內(nèi)聚低耦合的要求的。這個時候就需要解耦隅俘,當然解耦有很多種方法邻奠,而DI就是其中一種。不管任何一種解耦方法为居,都不是說使A和B完全沒有關(guān)系碌宴,而是把這種關(guān)系的實現(xiàn)變得隱晦,不那么直接蒙畴,但是又很容易實現(xiàn)贰镣,而且易于擴展,不像上面的代碼那樣膳凝,直接new一個B出來碑隆。
那為什么我們總是把IOC和DI聯(lián)系到一起呢?是因為DI的基本思想就是IOC蹬音,而體現(xiàn)IOC 思想的方法還有另外一個上煤,那就是Service Locator,這個方法好像涉及到的很少祟绊。
DI楼入,依賴注入,從字面意思就可以看出牧抽,依賴是通過外接注入的方式來實現(xiàn)的嘉熊。這就實現(xiàn)了解耦,而DI的方式通常有三種扬舒,
- 構(gòu)造器注入
- 屬性設(shè)置器注入
- 接口注入(我感覺接口注入是同時存在于上兩種注入方式的阐肤,而不應(yīng)該獨立出來)
以上的闡述只是為了先讓我們能對IOC和DI有一個感性的理解,那么IOC真正解決的問題是什么呢讲坎?
我們講了那么多主動被動的問題孕惜,那我們是從什么視角來看待這個問題的呢?
所謂為什么你是主動晨炕,而我不是主動呢衫画?這就需要一個參照物,那這個參照物是什么呢瓮栗?就是容器削罩,在容器中來體現(xiàn)主動和被動。
用白話來講费奸,就是由容器控制程序之間的關(guān)系弥激,而非傳統(tǒng)實現(xiàn)中,由程序代碼直接操控愿阐。這也就是所謂“控制反轉(zhuǎn)”的概念所在:控制權(quán)由應(yīng)用代碼中轉(zhuǎn)到了外部容器微服,控制權(quán)的轉(zhuǎn)移,是所謂“反轉(zhuǎn)”缨历,這是通常對IOC的一個解釋以蕴。
從容器的角度來看主動和被動,和由容器來控制程序之間的關(guān)系戈二,應(yīng)該是相通的舒裤,是一個意思。
IOC要解決的就是程序之間調(diào)用的一個問題觉吭,它應(yīng)該是一個思想層面的東西腾供,是一個中心,就像一支樂隊的指揮鲜滩,而程序就是樂器伴鳖,通過指揮來協(xié)調(diào)各種樂器,來演奏出美好的音樂來徙硅。
以下文字參考:http://www.cnblogs.com/gooddasenlin/archive/2009/03/02/1401631.html
Interface Driven Design 接口驅(qū)動
接口驅(qū)動有很多好處榜聂,可以提供不同靈活的子類實現(xiàn),增加代碼穩(wěn)定和健壯性等等嗓蘑,但是接口一定是需要實現(xiàn)的须肆,也就是如下語句遲早要執(zhí)行:AInterface a = new AInterfaceImp(); 這樣一來匿乃,耦合關(guān)系就產(chǎn)生了。
如:
Class A {
AInterface a;
A() {}
aMethod() {
a=newAInterfaceImp();
}
}
ClassA與AInterfaceImp就是依賴關(guān)系豌汇,如果想使用AInterface的另外一個實現(xiàn)就需要更改代碼了幢炸。
當然我們可以建立一個Factory來根據(jù)條件生成想要的AInterface的具體實現(xiàn),即:
InterfaceImplFactory {
AInterface create(Object condition) {
if(condition=condA) {
returnnewAInterfaceImpA();
} elseif(condition=condB) {
return new AInterfaceImpB();
} else {
return new AInterfaceImp();
}
}
}
表面上是在一定程度上緩解了以上問題拒贱,但實質(zhì)上這種代碼耦合并沒有改變宛徊。
通過IoC模式可以徹底解決這種耦合,它把耦合從代碼中移出去逻澳,放到統(tǒng)一的XML文件中闸天,通過一個容器在需要的時候把這個依賴關(guān)系形成,即把需要的接口實現(xiàn)注入到需要它的類中斜做,這可能就是“依賴注入”說法的來源了苞氮。
IOC模式系統(tǒng)中,通過引入實現(xiàn)IOC模式的IOC容器瓤逼,即可由IOC容器來管理對象的生命周期葱淳、依賴關(guān)系等,從而使得應(yīng)用程序的配置和依賴性規(guī)范與實際的應(yīng)用程序代碼分開抛姑。其中一個特點就是通過文本的配置文件進行應(yīng)用程序組件間相互關(guān)系的配置赞厕,而不用重新修改并編譯具體的代碼。
當前比較知名的IOC容器有:Pico Container定硝、Avalon 皿桑、Spring、JBoss蔬啡、HiveMind诲侮、EJB等。其中箱蟆,輕量級的有Pico Container沟绪、Avalon、Spring空猜、HiveMind等绽慈,超重量級的有EJB,而半輕半重的有容器有JBoss辈毯,Jdon等坝疼。
可以把IoC模式看做是工廠模式的升華,可以把IoC看作是一個大工廠谆沃,只不過這個大工廠里要生成的對象都是在XML文件中給出定義的钝凶,然后利用Java 的“反射”編程,根據(jù)XML中給出的類名生成相應(yīng)的對象唁影。從實現(xiàn)來看耕陷,IoC是把以前在工廠方法里寫死的對象生成代碼掂名,改變?yōu)橛蒟ML文件來定義,也就是把工廠和對象生成這兩者獨立分隔開來哟沫,目的就是提高靈活性和可維護性铆隘。
IoC中最基本的Java技術(shù)就是“反射”編程。反射又是一個生澀的名詞南用,通俗的說反射就是根據(jù)給出的類名(字符串)來生成對象。這種編程方式可以讓對象在生成時才決定要生成哪一種對象掏湾。反射的應(yīng)用是很廣泛的裹虫,象Hibernate、String中都是用“反射”做為最基本的技術(shù)手段融击。
IoC最大的好處是什么筑公?因為把對象生成放在了XML里定義,所以當我們需要換一個實現(xiàn)子類將會變成很簡單(一般這樣的對象都是現(xiàn)實于某種接口的)尊浪,只要修改XML就可以了匣屡。
參考:http://www.cnblogs.com/niuniu1985/archive/2010/01/13/1646375.html