今天看了一下設(shè)計(jì)模式的依賴倒置原則,覺(jué)得這個(gè)原則真的是太好了宠互,如果按這個(gè)原則去開(kāi)發(fā)的話浴讯,以后在維護(hù)項(xiàng)目功能的時(shí)候,一定會(huì)省很多事,會(huì)很大程度上降低類與類之間的耦合尔邓,當(dāng)軟件增加新功能時(shí)晾剖,修改或者增加時(shí)也不會(huì)影響原來(lái)類的邏輯,會(huì)很大程度上降低修改程序所造成的風(fēng)險(xiǎn)梯嗽,增強(qiáng)軟件的穩(wěn)定性.
下面就根據(jù)我自己的理解給大家給大家簡(jiǎn)要說(shuō)一下
定義:高層模塊不應(yīng)該依賴低層模塊齿尽,二者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細(xì)節(jié)灯节;細(xì)節(jié)應(yīng)該依賴抽象(聽(tīng)起來(lái)很復(fù)雜的樣子循头,等會(huì)看了代碼就會(huì)清晰很多了)
問(wèn)題由來(lái):類A直接依賴類B绵估,假如要將類A改為依賴類C,則必須通過(guò)修改類A的代碼來(lái)達(dá)成卡骂。這種場(chǎng)景下国裳,類A一般是高層模塊,負(fù)責(zé)復(fù)雜的業(yè)務(wù)邏輯:類B和類C是低層模塊全跨,負(fù)責(zé)基本的原子操作缝左;假如修改類A,會(huì)給程序帶來(lái)不必要的風(fēng)險(xiǎn)浓若。
解決方案:將類A修改為依賴接口I渺杉,類B和類C各自實(shí)現(xiàn)接口I,類A通過(guò)接口I間接與類B或者類C發(fā)生聯(lián)系挪钓,則會(huì)大大降低修改類A的幾率是越。
依賴倒置原則基于這樣一個(gè)事實(shí):相對(duì)于細(xì)節(jié)的多變性,抽象的東西要穩(wěn)定的多碌上。以抽象為基礎(chǔ)搭建起來(lái)的架構(gòu)比以細(xì)節(jié)為基礎(chǔ)搭建起來(lái)的架構(gòu)要穩(wěn)定的多倚评。在java中,抽象指的是接口或者抽象類馏予,細(xì)節(jié)就是具體的實(shí)現(xiàn)類天梧,使用接口或者抽象類的目的是制定好規(guī)范和契約,而不去涉及任何具體的操作霞丧,把展現(xiàn)細(xì)節(jié)的任務(wù)交給他們的實(shí)現(xiàn)類去完成腿倚。
依賴倒置原則的核心思想是面向接口編程,我們依舊用一個(gè)例子來(lái)說(shuō)明面向接口編程比相對(duì)于面向?qū)崿F(xiàn)編程好在什么地方蚯妇。場(chǎng)景是這樣的敷燎,母親給孩子講故事,只要給她一本書箩言,她就可以照著書給孩子講故事了硬贯。代碼如下:
class Book{
public String getContent(){
return "很久很久以前有一個(gè)阿拉伯的故事……";
}
}
class Mother{
public void narrate(Book book){
System.out.println("媽媽開(kāi)始講故事");
System.out.println(book.getContent());
}
}
public class Client{
public static void main(String[] args){
Mother mother = new Mother();
mother.narrate(new Book());
}
}
運(yùn)行結(jié)果:
媽媽開(kāi)始講故事
很久很久以前有一個(gè)阿拉伯的故事……
我們的程序正在肆無(wú)忌憚的運(yùn)行著,每天悠哉悠哉的陨收,突然有一天......
需求開(kāi)始變化了 需求變成這樣:不是給書而是給一份報(bào)紙饭豹,讓這位母親講一下報(bào)紙上的故事,報(bào)紙的代碼如下:
class Newspaper{
public String getContent(){
return "林書豪38+7領(lǐng)導(dǎo)尼克斯擊敗湖人……";
}
}
這位母親卻辦不到务漩,因?yàn)樗尤徊粫?huì)讀報(bào)紙上的故事拄衰,這太荒唐了,只是將書換成報(bào)紙饵骨,居然必須要修改Mother才能讀翘悉。假如以后需求換成雜志呢?換成網(wǎng)頁(yè)呢居触?還要不斷地修改Mother妖混,這顯然不是好的設(shè)計(jì)老赤。原因就是Mother與Book之間的耦合性太高了,必須降低他們之間的耦合度才行制市。
我們引入一個(gè)抽象的接口IReader抬旺。讀物,只要是帶字的都屬于讀物:
interface IReader{
public String getContent();
}
//Mother類與接口IReader發(fā)生依賴關(guān)系祥楣,而Book和Newspaper都屬于讀物的范疇开财,他們各自都去實(shí)現(xiàn)IReader接口,這樣就符合依賴倒置原則了误褪,代碼修改為:
class Newspaper implements IReader {
public String getContent(){
return "林書豪17+9助尼克斯擊敗老鷹……";
}
}
class Book implements IReader{
public String getContent(){
return "很久很久以前有一個(gè)阿拉伯的故事……";
}
}
class Mother{
public void narrate(IReader reader){
System.out.println("媽媽開(kāi)始講故事");
System.out.println(reader.getContent());
}
}
public class Client{
public static void main(String[] args){
Mother mother = new Mother();
mother.narrate(new Book());
mother.narrate(new Newspaper());
}
}
運(yùn)行結(jié)果:
媽媽開(kāi)始講故事
很久很久以前有一個(gè)阿拉伯的故事……
媽媽開(kāi)始講故事
林書豪17+9助尼克斯擊敗老鷹……
這樣修改后床未,無(wú)論以后怎樣擴(kuò)展Client類,都不需要再修改Mother類了振坚。這只是一個(gè)簡(jiǎn)單的例子,實(shí)際情況中斋扰,代表高層模塊的Mother類將負(fù)責(zé)完成主要的業(yè)務(wù)邏輯渡八,一旦需要對(duì)它進(jìn)行修改,引入錯(cuò)誤的風(fēng)險(xiǎn)極大传货。所以遵循依賴倒置原則可以降低類之間的耦合性屎鳍,提高系統(tǒng)的穩(wěn)定性,降低修改程序造成的風(fēng)險(xiǎn)问裕。
采用依賴倒置原則給多人并行開(kāi)發(fā)帶來(lái)了極大的便利逮壁,比如上例中,原本Mother類與Book類直接耦合時(shí)粮宛,Mother類必須等Book類編碼完成后才可以進(jìn)行編碼窥淆,因?yàn)镸other類依賴于Book類。修改后的程序則可以同時(shí)開(kāi)工巍杈,互不影響忧饭,因?yàn)镸other與Book類一點(diǎn)關(guān)系也沒(méi)有。參與協(xié)作開(kāi)發(fā)的人越多筷畦、項(xiàng)目越龐大词裤,采用依賴導(dǎo)致原則的意義就越重大。現(xiàn)在很流行的TDD開(kāi)發(fā)模式就是依賴倒置原則最成功的應(yīng)用鳖宾。
傳遞依賴關(guān)系有三種方式吼砂,以上的例子中使用的方法是接口傳遞,另外還有兩種傳遞方式:構(gòu)造方法傳遞和setter方法傳遞鼎文,相信用過(guò)Spring框架的渔肩,對(duì)依賴的傳遞方式一定不會(huì)陌生。
在實(shí)際編程中拇惋,我們一般需要做到如下3點(diǎn):
● 低層模塊盡量都要有抽象類或接口赖瞒,或者兩者都有女揭。
● 變量的聲明類型盡量是抽象類或接口。
● 使用繼承時(shí)遵循里氏替換原則栏饮。
依賴倒置原則的核心就是要我們面向接口編程吧兔,理解了面向接口編程,也就理解了依賴倒置袍嬉。
好了境蔼,就先說(shuō)到這里吧!設(shè)計(jì)模式中的這些原則真正在項(xiàng)目中運(yùn)用才能發(fā)揮其作用伺通,理論只是幫助我們以后更好的去實(shí)踐箍土,實(shí)戰(zhàn)才是最重要的,但也不能輕視一些理論知識(shí)罐监,希望能和大家共勉吴藻!一起進(jìn)步