JAVA設(shè)計(jì)模式總結(jié)之六大設(shè)計(jì)原則

學(xué)習(xí)設(shè)計(jì)模式挣柬,首先要學(xué)習(xí)的就是設(shè)計(jì)原則钥顽。

設(shè)計(jì)原則

1. 單一職責(zé)

簡(jiǎn)單通俗的來(lái)說(shuō):一個(gè)類只負(fù)責(zé)一項(xiàng)職責(zé)。

遵循單一職責(zé)的優(yōu)點(diǎn)有:

  • 可以降低類的復(fù)雜度舞箍,一個(gè)類只負(fù)責(zé)一項(xiàng)職責(zé)舰褪,其邏輯肯定要比負(fù)責(zé)多項(xiàng)職責(zé)簡(jiǎn)單的多;

  • 提高類的可讀性疏橄,提高系統(tǒng)的可維護(hù)性占拍;

  • 變更引起的風(fēng)險(xiǎn)降低略就,變更是必然的,如果單一職責(zé)原則遵守的好晃酒,當(dāng)修改一個(gè)功能時(shí)表牢,可以顯著降低對(duì)其他功能的影響。

2. 里氏替換原則 (Liskov Substitution Principle)

里氏替換原則(Liskov Substitution Principle LSP)面向?qū)ο笤O(shè)計(jì)的基本原則之一贝次。 里氏替換原則中說(shuō)崔兴,任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)蛔翅。 LSP是繼承復(fù)用的基石敲茄,只有當(dāng)衍生類可以替換掉基類,軟件單位的功能不受到影響時(shí)搁宾,基類才能真正被復(fù)用折汞,而衍生類也能夠在基類的基礎(chǔ)上增加新的行為。里氏替換原則是對(duì)“開(kāi)-閉”原則的補(bǔ)充盖腿。實(shí)現(xiàn)“開(kāi)-閉”原則的關(guān)鍵步驟就是抽象化爽待。而基類與子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn),所以里氏替換原則是對(duì)實(shí)現(xiàn)抽象化的具體步驟的規(guī)范翩腐。

通俗簡(jiǎn)單的說(shuō)就是:子類可以擴(kuò)展父類的功能鸟款,但不能改變父類原有的功能。

再次來(lái)理解里氏替換原則:子類可以擴(kuò)展父類的功能茂卦,但不能改變父類原有的功能何什。它包含以下4層含義:

  • 子類可以實(shí)現(xiàn)父類的抽象方法,但不能覆蓋父類的非抽象方法等龙。

  • 子類中可以增加自己特有的方法处渣。

  • 當(dāng)子類的方法重載父類的方法時(shí),方法的前置條件(即方法的形參)要比父類方法的輸入?yún)?shù)更寬松蛛砰」拚唬【注意區(qū)分重載和重寫】

  • 當(dāng)子類的方法實(shí)現(xiàn)父類的抽象方法時(shí),方法的后置條件(即方法的返回值)要比父類更嚴(yán)格泥畅。

3. 依賴倒置原則 (Dependence Inversion Principle)

所謂依賴倒置原則(Dependence Inversion Principle)就是要依賴于抽象荠诬,不要依賴于具體。實(shí)現(xiàn)開(kāi)閉原則的關(guān)鍵是抽象化位仁,并且從抽象化導(dǎo)出具體化實(shí)現(xiàn)柑贞,如果說(shuō)開(kāi)閉原則是面向?qū)ο笤O(shè)計(jì)的目標(biāo)的話,那么依賴倒置原則就是面向?qū)ο笤O(shè)計(jì)的主要手段聂抢。

定義:高層模塊不應(yīng)該依賴低層模塊钧嘶,二者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細(xì)節(jié)琳疏;細(xì)節(jié)應(yīng)該依賴抽象康辑。

通俗點(diǎn)說(shuō):要求對(duì)抽象進(jìn)行編程摄欲,不要對(duì)實(shí)現(xiàn)進(jìn)行編程轿亮,這樣就降低了客戶與實(shí)現(xiàn)模塊間的耦合疮薇。

依賴倒置原則基于這樣一個(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)類去完成掠抬。

依賴倒置原則的核心思想是面向接口編程。

傳遞依賴關(guān)系有三種方式校哎,以上的例子中使用的方法是接口傳遞两波,另外還有兩種傳遞方式:構(gòu)造方法傳遞setter方法傳遞

在實(shí)際編程中闷哆,我們一般需要做到如下3點(diǎn):

  • 低層模塊盡量都要有抽象類或接口腰奋,或者兩者都有”д【可能會(huì)被人用到的】

  • 變量的聲明類型盡量是抽象類或接口劣坊。

  • 使用繼承時(shí)遵循里氏替換原則。

依賴倒置原則的核心就是要我們面向接口編程屈留,理解了面向接口編程局冰,也就理解了依賴倒置。

4. 接口隔離原則 (Interface Segregation Principle)

其原則字面的意思是:使用多個(gè)隔離的接口灌危,比使用單個(gè)接口要好康二。本意降低類之間的耦合度,而設(shè)計(jì)模式就是一個(gè)軟件的設(shè)計(jì)思想乍狐,從大型軟件架構(gòu)出發(fā)赠摇,為了升級(jí)和維護(hù)方便。所以上文中多次出現(xiàn):降低依賴浅蚪,降低耦合藕帜。

原定義:客戶端不應(yīng)該依賴它不需要的接口;一個(gè)類對(duì)另一個(gè)類的依賴應(yīng)該建立在最小的接口上惜傲。

接口隔離原則的含義是:建立單一接口洽故,不要建立龐大臃腫的接口,盡量細(xì)化接口盗誊,接口中的方法盡量少时甚。也就是說(shuō)隘弊,我們要為各個(gè)類建立專用的接口,而不要試圖去建立一個(gè)很龐大的接口供所有依賴它的類去調(diào)用荒适。在程序設(shè)計(jì)中梨熙,依賴幾個(gè)專用的接口要比依賴一個(gè)綜合的接口更靈活。接口是設(shè)計(jì)時(shí)對(duì)外部設(shè)定的“契約”刀诬,通過(guò)分散定義多個(gè)接口咽扇,可以預(yù)防外來(lái)變更的擴(kuò)散,提高系統(tǒng)的靈活性和可維護(hù)性陕壹。

說(shuō)到這里质欲,很多人會(huì)覺(jué)的接口隔離原則跟之前的單一職責(zé)原則很相似,其實(shí)不然糠馆。其一嘶伟,單一職責(zé)原則原注重的是職責(zé);而接口隔離原則注重對(duì)接口依賴的隔離又碌。其二九昧,單一職責(zé)原則主要是約束類,其次才是接口和方法赠橙,它針對(duì)的是程序中的實(shí)現(xiàn)和細(xì)節(jié)耽装;而接口隔離原則主要約束接口,主要針對(duì)抽象期揪,針對(duì)程序整體框架的構(gòu)建掉奄。

采用接口隔離原則對(duì)接口進(jìn)行約束時(shí),要注意以下幾點(diǎn):

  • 接口盡量小凤薛,但是要有限度姓建。對(duì)接口進(jìn)行細(xì)化可以提高程序設(shè)計(jì)靈活性是不掙的事實(shí),但是如果過(guò)小缤苫,則會(huì)造成接口數(shù)量過(guò)多速兔,使設(shè)計(jì)復(fù)雜化。所以一定要適度活玲。

  • 為依賴接口的類定制服務(wù)涣狗,只暴露給調(diào)用的類它需要的方法,它不需要的方法則隱藏起來(lái)舒憾。只有專注地為一個(gè)模塊提供定制服務(wù)镀钓,才能建立最小的依賴關(guān)系。

  • 提高內(nèi)聚镀迂,減少對(duì)外交互丁溅。使接口用最少的方法去完成最多的事情。

運(yùn)用接口隔離原則探遵,一定要適度窟赏,接口設(shè)計(jì)的過(guò)大或過(guò)小都不好妓柜。設(shè)計(jì)接口的時(shí)候,只有多花些時(shí)間去思考和籌劃涯穷,才能準(zhǔn)確地實(shí)踐這一原則棍掐。

5. 迪米特法則(最少知道原則) (Demeter Principle)

為什么叫最少知道原則,就是說(shuō):一個(gè)實(shí)體應(yīng)當(dāng)盡量少的與其他實(shí)體之間發(fā)生相互作用求豫,使得系統(tǒng)功能模塊相對(duì)獨(dú)立塌衰。也就是說(shuō)一個(gè)軟件實(shí)體應(yīng)當(dāng)盡可能少的與其他實(shí)體發(fā)生相互作用。這樣蝠嘉,當(dāng)一個(gè)模塊修改時(shí),就會(huì)盡量少的影響其他的模塊杯巨,擴(kuò)展會(huì)相對(duì)容易蚤告,這是對(duì)軟件實(shí)體之間通信的限制,它要求限制軟件實(shí)體之間通信的寬度和深度服爷。

定義:一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最少的了解杜恰。

問(wèn)題由來(lái):類與類之間的關(guān)系越密切,耦合度越大仍源,當(dāng)一個(gè)類發(fā)生改變時(shí)心褐,對(duì)另一個(gè)類的影響也越大。

解決方案:盡量降低類與類之間的耦合笼踩。

自從我們接觸編程開(kāi)始逗爹,就知道了軟件編程的總的原則:低耦合,高內(nèi)聚嚎于。無(wú)論是面向過(guò)程編程還是面向?qū)ο缶幊叹蚨挥惺垢鱾€(gè)模塊之間的耦合盡量的低,才能提高代碼的復(fù)用率于购。低耦合的優(yōu)點(diǎn)不言而喻袍睡,但是怎么樣編程才能做到低耦合呢?那正是迪米特法則要去完成的肋僧。

迪米特法則又叫最少知道原則斑胜,最早是在1987年由美國(guó)Northeastern University的Ian Holland提出。通俗的來(lái)講嫌吠,就是一個(gè)類對(duì)自己依賴的類知道的越少越好止潘。也就是說(shuō),對(duì)于被依賴的類來(lái)說(shuō)居兆,無(wú)論邏輯多么復(fù)雜覆山,都盡量地的將邏輯封裝在類的內(nèi)部,對(duì)外除了提供的public方法,不對(duì)外泄漏任何信息拦键。迪米特法則還有一個(gè)更簡(jiǎn)單的定義:只與直接的朋友通信千扶。首先來(lái)解釋一下什么是直接的朋友:每個(gè)對(duì)象都會(huì)與其他對(duì)象有耦合關(guān)系汰翠,只要兩個(gè)對(duì)象之間有耦合關(guān)系翎朱,我們就說(shuō)這兩個(gè)對(duì)象之間是朋友關(guān)系侄泽。耦合的方式很多懈贺,依賴犀忱、關(guān)聯(lián)钞它、組合拜银、聚合等。其中遭垛,我們稱出現(xiàn)成員變量尼桶、方法參數(shù)、方法返回值中的類為直接的朋友锯仪,而出現(xiàn)在局部變量中的類則不是直接的朋友泵督。也就是說(shuō),陌生的類最好不要作為局部變量的形式出現(xiàn)在類的內(nèi)部庶喜。

過(guò)分的使用迪米特原則小腊,會(huì)產(chǎn)生大量這樣的中介和傳遞類,導(dǎo)致系統(tǒng)復(fù)雜度變大久窟。所以在采用迪米特法則時(shí)要反復(fù)權(quán)衡秩冈,既做到結(jié)構(gòu)清晰,又要高內(nèi)聚低耦合斥扛。

6. 開(kāi)閉原則(Open Close Principle)

開(kāi)閉原則就是說(shuō)對(duì)擴(kuò)展開(kāi)放入问,對(duì)修改關(guān)閉。在程序需要進(jìn)行拓展的時(shí)候犹赖,不能去修改原有的代碼队他,實(shí)現(xiàn)一個(gè)熱插拔的效果。所以一句話概括就是:為了使程序的擴(kuò)展性好峻村,易于維護(hù)和升級(jí)麸折。想要達(dá)到這樣的效果,需要面向接口編程粘昨。

定義:一個(gè)軟件實(shí)體如類垢啼、模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉张肾。

問(wèn)題由來(lái):在軟件的生命周期內(nèi)芭析,因?yàn)樽兓⑸?jí)和維護(hù)等原因需要對(duì)軟件原有代碼進(jìn)行修改時(shí)吞瞪,可能會(huì)給舊代碼中引入錯(cuò)誤馁启,也可能會(huì)使我們不得不對(duì)整個(gè)功能進(jìn)行重構(gòu),并且需要原有代碼經(jīng)過(guò)重新測(cè)試。

解決方案:當(dāng)軟件需要變化時(shí)惯疙,盡量通過(guò)擴(kuò)展軟件實(shí)體的行為來(lái)實(shí)現(xiàn)變化翠勉,而不是通過(guò)修改已有的代碼來(lái)實(shí)現(xiàn)變化。

開(kāi)閉原則是面向?qū)ο笤O(shè)計(jì)中最基礎(chǔ)的設(shè)計(jì)原則霉颠,它指導(dǎo)我們?nèi)绾谓⒎€(wěn)定靈活的系統(tǒng)对碌。開(kāi)閉原則可能是設(shè)計(jì)模式六項(xiàng)原則中定義最模糊的一個(gè)了,它只告訴我們對(duì)擴(kuò)展開(kāi)放蒿偎,對(duì)修改關(guān)閉朽们,可是到底如何才能做到對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉诉位,并沒(méi)有明確的告訴我們骑脱。以前,如果有人告訴我“你進(jìn)行設(shè)計(jì)的時(shí)候一定要遵守開(kāi)閉原則”不从,我會(huì)覺(jué)的他什么都沒(méi)說(shuō)惜姐,但貌似又什么都說(shuō)了。因?yàn)殚_(kāi)閉原則真的太虛了椿息。

如果仔細(xì)思考以及仔細(xì)閱讀很多設(shè)計(jì)模式的文章后,會(huì)發(fā)現(xiàn)其實(shí)坷衍,我們遵循設(shè)計(jì)模式前面5大原則寝优,以及使用23種設(shè)計(jì)模式的目的就是遵循開(kāi)閉原則。也就是說(shuō)枫耳,只要我們對(duì)前面5項(xiàng)原則遵守的好了乏矾,設(shè)計(jì)出的軟件自然是符合開(kāi)閉原則的,這個(gè)開(kāi)閉原則更像是前面五項(xiàng)原則遵守程度的“平均得分”迁杨,前面5項(xiàng)原則遵守的好钻心,平均分自然就高,說(shuō)明軟件設(shè)計(jì)開(kāi)閉原則遵守的好铅协;如果前面5項(xiàng)原則遵守的不好捷沸,則說(shuō)明開(kāi)閉原則遵守的不好。

開(kāi)閉原則無(wú)非就是想表達(dá)這樣一層意思:用抽象構(gòu)建框架狐史,用實(shí)現(xiàn)擴(kuò)展細(xì)節(jié)痒给。因?yàn)槌橄箪`活性好,適應(yīng)性廣骏全,只要抽象的合理苍柏,可以基本保持軟件架構(gòu)的穩(wěn)定。而軟件中易變的細(xì)節(jié)姜贡,我們用從抽象派生的實(shí)現(xiàn)類來(lái)進(jìn)行擴(kuò)展试吁,當(dāng)軟件需要發(fā)生變化時(shí),我們只需要根據(jù)需求重新派生一個(gè)實(shí)現(xiàn)類來(lái)擴(kuò)展就可以了楼咳。當(dāng)然前提是我們的抽象要合理熄捍,要對(duì)需求的變更有前瞻性和預(yù)見(jiàn)性才行烛恤。

說(shuō)到這里,再回想一下前面說(shuō)的5項(xiàng)原則治唤,恰恰是告訴我們用抽象構(gòu)建框架棒动,用實(shí)現(xiàn)擴(kuò)展細(xì)節(jié)的注意事項(xiàng)而已:?jiǎn)我宦氊?zé)原則告訴我們實(shí)現(xiàn)類要職責(zé)單一;里氏替換原則告訴我們不要破壞繼承體系宾添;依賴倒置原則告訴我們要面向接口編程船惨;接口隔離原則告訴我們?cè)谠O(shè)計(jì)接口的時(shí)候要精簡(jiǎn)單一;迪米特法則告訴我們要降低耦合缕陕。而開(kāi)閉原則是總綱粱锐,他告訴我們要對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉扛邑。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末怜浅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蔬崩,更是在濱河造成了極大的恐慌恶座,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沥阳,死亡現(xiàn)場(chǎng)離奇詭異跨琳,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)桐罕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門脉让,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人功炮,你說(shuō)我怎么就攤上這事溅潜。” “怎么了薪伏?”我有些...
    開(kāi)封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵滚澜,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我毅该,道長(zhǎng)博秫,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任眶掌,我火速辦了婚禮挡育,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘朴爬。我一直安慰自己即寒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著母赵,像睡著了一般逸爵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凹嘲,一...
    開(kāi)封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天师倔,我揣著相機(jī)與錄音,去河邊找鬼周蹭。 笑死趋艘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的凶朗。 我是一名探鬼主播瓷胧,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼棚愤!你這毒婦竟也來(lái)了搓萧?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宛畦,失蹤者是張志新(化名)和其女友劉穎瘸洛,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體次和,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡货矮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了斯够。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡喧锦,死狀恐怖读规,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情燃少,我是刑警寧澤束亏,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站阵具,受9級(jí)特大地震影響碍遍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜阳液,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一怕敬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帘皿,春花似錦东跪、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)丁恭。三九已至,卻和暖如春斋日,著一層夾襖步出監(jiān)牢的瞬間牲览,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工恶守, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留第献,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓熬的,卻偏偏與公主長(zhǎng)得像痊硕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子押框,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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