- s( Single-Resposibility Principle ): 單一職責(zé)原則。
- o( Open-Closed principle ): 開放封閉原則临扮。
- l( Liskov-Substituion Principle ): 里氏替換原則孤个。
- i( Interface-Segregation Principle ): 接口隔離原則剃允。
- d( Dependecy-Inversion Principle ): 依賴倒置原則。
- 合成/聚合復(fù)用齐鲤。
- 迪米特法則
單一職責(zé)原則( Single-Resposibility Principle )
一個(gè)類只做它該做的事情斥废。
是指一個(gè)類的功能要單一, 一個(gè)類只負(fù)責(zé)一個(gè)職責(zé)给郊。 一個(gè)類只做它該做的事情(高內(nèi)聚)牡肉。 在面向?qū)ο笾校?如果只讓一個(gè)類完成它該做的事, 而不涉及與它無關(guān)的領(lǐng)域就是踐行了高內(nèi)聚的原則淆九。
單一職責(zé)原則想表達(dá)的就是"高內(nèi)聚"统锤,寫代碼最終極的原則只有六個(gè)字"高內(nèi)聚毛俏、低耦合",就如同葵花寶典或辟邪劍譜的中心思想就八個(gè)字"欲練此功必先自宮"饲窿,所謂的高內(nèi)聚就是一個(gè)代碼模塊只完成一項(xiàng)功能拧抖,在面向?qū)ο笾校绻蛔屢粋€(gè)類完成它該做的事免绿,而不涉及與它無關(guān)的領(lǐng)域就是踐行了高內(nèi)聚的原則,這個(gè)類就只有單一職責(zé)擦盾。
一個(gè)好的軟件系統(tǒng)嘲驾,它里面的每個(gè)功能模塊也應(yīng)該是可以輕易的拿到其他系統(tǒng)中使用的,這樣才能實(shí)現(xiàn)軟件復(fù)用的目標(biāo)迹卢。
開放封閉原則( Open-Closed principle )
軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放辽故, 對(duì)修改關(guān)閉。 對(duì)擴(kuò)展開放腐碱, 意味著有新的需求或變化時(shí)誊垢, 可以對(duì)現(xiàn)有代碼進(jìn)行擴(kuò)展, 以適應(yīng)新的情況症见。 對(duì)修改封閉喂走, 意味著類一旦設(shè)計(jì)完成, 就可以獨(dú)立其工作谋作, 而不要對(duì)類盡任何修改芋肠。 在開發(fā)階段, 我們都知道遵蚜, 如果對(duì)一個(gè)功能進(jìn)行擴(kuò)展帖池, 如果只是一味地對(duì)方法進(jìn)行修改, 可能會(huì)造成一些問題吭净, 諸如可能會(huì)引入新的 bug睡汹, 或者增加代碼的復(fù)雜度, 對(duì)代碼結(jié)構(gòu)造成破壞寂殉、 冗余囚巴, 還需要重新進(jìn)行全面的測試。 那么該怎么解決這些問題不撑? 很簡單文兢, 這就需要系統(tǒng)能夠支持?jǐn)U展, 只有擴(kuò)展性良好的系統(tǒng)焕檬,才能在不進(jìn)行修改已有實(shí)現(xiàn)代碼的基礎(chǔ)上姆坚, 引進(jìn)新的功能。
要做到開閉有兩個(gè)要點(diǎn):
①抽象是關(guān)鍵实愚,一個(gè)系統(tǒng)中如果沒有抽象類或接口系統(tǒng)就沒有擴(kuò)展點(diǎn)兼呵;
②封裝可變性兔辅,將系統(tǒng)中的各種可變因素封裝到一個(gè)繼承結(jié)構(gòu)中,如果多個(gè)可變因素混雜在一起击喂,系統(tǒng)將變得復(fù)雜而換亂
里氏替換原則( Liskov-Substituion Principle )
任何使用基類的地方维苔, 都能夠使用子類替換, 而且在替換子類后懂昂, 系統(tǒng)能夠正常工作介时。 子類一定是增加父類的能力而不是減少父類的能力,因?yàn)樽宇惐雀割惖哪芰Ω啵?把能力多的對(duì)象當(dāng)成能力少的對(duì)象來用當(dāng)然沒有任何問題凌彬。 一個(gè)軟件實(shí)體如果使用的是一個(gè)基類沸柔, 那么當(dāng)把這個(gè)基類替換成繼承該基類的子類, 程序的行為不會(huì)發(fā)生任何變化铲敛。 軟件實(shí)體察覺不出基類對(duì)象和子類對(duì)象的區(qū)別褐澎。
關(guān)于里氏替換原則的描述,簡單的說就是能用父類型的地方就一定能使用子類型伐蒋。里氏替換原則可以檢查繼承關(guān)系是否合理工三,如果一個(gè)繼承關(guān)系違背了里氏替換原則,那么這個(gè)繼承關(guān)系一定是錯(cuò)誤的先鱼,需要對(duì)代碼進(jìn)行重構(gòu)俭正。例如讓貓繼承狗,或者狗繼承貓焙畔,又或者讓正方形繼承長方形都是錯(cuò)誤的繼承關(guān)系段审,因?yàn)槟愫苋菀渍业竭`反里氏替換原則的場景。需要注意的是:子類一定是增加父類的能力而不是減少父類的能力闹蒜,因?yàn)樽宇惐雀割惖哪芰Ω嗨峦鳎涯芰Χ嗟膶?duì)象當(dāng)成能力少的對(duì)象來用當(dāng)然沒有任何問題。
接口隔離原則( Interface-Segregation Principle )
即應(yīng)該將接口粒度最小化绷落, 將功能劃分到每一個(gè)不能再分的子角色姥闪, 為每一個(gè)子角色創(chuàng)建接口, 通過這樣砌烁, 才不會(huì)讓接口的實(shí)現(xiàn)類實(shí)現(xiàn)一些不必要的功能筐喳。 建立單一的接口, 不要建立臃腫的龐大的接口函喉, 也就是說接口的方法盡量少避归。 接口要小而專, 絕不能大而全管呵。 臃腫的接口是對(duì)接口的污染梳毙,既然接口表示能力, 那么一個(gè)接口只應(yīng)該描述一種能力捐下, 接口也應(yīng)該是高度內(nèi)聚的账锹。
例如萌业,琴棋書畫就應(yīng)該分別設(shè)計(jì)為四個(gè)接口,而不應(yīng)設(shè)計(jì)成一個(gè)接口中的四個(gè)方法奸柬,因?yàn)槿绻O(shè)計(jì)成一個(gè)接口中的四個(gè)方法生年,那么這個(gè)接口很難用,畢竟琴棋書畫四樣都精通的人還是少數(shù)廓奕,而如果設(shè)計(jì)成四個(gè)接口抱婉,會(huì)幾項(xiàng)就實(shí)現(xiàn)幾個(gè)接口,這樣的話每個(gè)接口被復(fù)用的可能性是很高的桌粉。Java中的接口代表能力授段、代表約定、代表角色番甩,能否正確的使用接口一定是編程水平高低的重要標(biāo)識(shí)。
依賴倒置原則( Dependecy-Inversion Principle )
即我們的類要依賴于抽象届搁, 而不是依賴于具體缘薛, 也就是我們經(jīng)常聽到的“要面向接口編程” 。 (該原則說得具體一些就是聲明方法的參數(shù)類型卡睦、 方法的返回類型宴胧、 變量的引用類型時(shí), 盡可能使用抽象類型而不用具體類型表锻, 因?yàn)槌橄箢愋涂梢员凰娜魏我粋€(gè)子類型所替代) ?恕齐。 依賴倒置原則的本質(zhì)就是通過抽象(抽象類或接口) 使各個(gè)類或模塊的實(shí)現(xiàn)彼此獨(dú)立, 不相互影響瞬逊,實(shí)現(xiàn)模塊間的松耦合显歧。 減少類間的耦合性。
合成聚合復(fù)用原則
優(yōu)先使用聚合或合成關(guān)系復(fù)用代碼确镊。
通過繼承來復(fù)用代碼是面向?qū)ο蟪绦蛟O(shè)計(jì)中被濫用得最多的東西士骤,因?yàn)樗械慕炭茣紵o一例外的對(duì)繼承進(jìn)行了鼓吹從而誤導(dǎo)了初學(xué)者,類與類之間簡單的說有三種關(guān)系蕾域,Is-A關(guān)系拷肌、Has-A關(guān)系、Use-A關(guān)系旨巷,分別代表繼承巨缘、關(guān)聯(lián)和依賴。其中采呐,關(guān)聯(lián)關(guān)系根據(jù)其關(guān)聯(lián)的強(qiáng)度又可以進(jìn)一步劃分為關(guān)聯(lián)若锁、聚合和合成,但說白了都是Has-A關(guān)系斧吐,合成聚合復(fù)用原則想表達(dá)的是優(yōu)先考慮Has-A關(guān)系而不是Is-A關(guān)系復(fù)用代碼拴清,原因嘛可以自己從百度上找到一萬個(gè)理由靶病,需要說明的是,即使在Java的API中也有不少濫用繼承的例子口予,例如Properties類繼承了Hashtable類娄周,Stack類繼承了Vector類,這些繼承明顯就是錯(cuò)誤的沪停,更好的做法是在Properties類中放置一個(gè)Hashtable類型的成員并且將其鍵和值都設(shè)置為字符串來存儲(chǔ)數(shù)據(jù)煤辨,而Stack類的設(shè)計(jì)也應(yīng)該是在Stack類中放一個(gè)Vector對(duì)象來存儲(chǔ)數(shù)據(jù)。記啄菊拧:任何時(shí)候都不要繼承工具類众辨,工具是可以擁有并可以使用的,而不是拿來繼承的舷礼。
迪米特法則
迪米特法則又叫最少知識(shí)原則鹃彻,一個(gè)對(duì)象應(yīng)當(dāng)對(duì)其他對(duì)象有盡可能少的了解。
類與類之間的關(guān)系越密切妻献,耦合度越大蛛株,當(dāng)一個(gè)類發(fā)生改變時(shí),對(duì)另一個(gè)類的影響也越大育拨。解決方案:盡量降低類與類之間的耦合谨履。
自從我們接觸編程開始,就知道了軟件編程的總的原則:低耦合熬丧,高內(nèi)聚笋粟。無論是面向過程編程還是面向?qū)ο缶幊蹋挥惺垢鱾€(gè)模塊之間的耦合盡量的低析蝴,才能提高代碼的復(fù)用率害捕。低耦合的優(yōu)點(diǎn)不言而喻,但是怎么樣編程才能做到低耦合呢闷畸?那正是迪米特法則要去完成的吨艇。
迪米特法則又叫最少知道原則,最早是在1987年由美國Northeastern University的Ian Holland提出腾啥。通俗的來講东涡,就是一個(gè)類對(duì)自己依賴的類知道的越少越好。也就是說倘待,對(duì)于被依賴的類來說疮跑,無論邏輯多么復(fù)雜,都盡量地的將邏輯封裝在類的內(nèi)部凸舵,對(duì)外除了提供的public方法祖娘,不對(duì)外泄漏任何信息。迪米特法則還有一個(gè)更簡單的定義:只與直接的朋友通信啊奄。首先來解釋一下什么是直接的朋友:每個(gè)對(duì)象都會(huì)與其他對(duì)象有耦合關(guān)系渐苏,只要兩個(gè)對(duì)象之間有耦合關(guān)系掀潮,我們就說這兩個(gè)對(duì)象之間是朋友關(guān)系。耦合的方式很多琼富,依賴仪吧、關(guān)聯(lián)、組合鞠眉、聚合等薯鼠。其中,我們稱出現(xiàn)成員變量械蹋、方法參數(shù)出皇、方法返回值中的類為直接的朋友,而出現(xiàn)在局部變量中的類則不是直接的朋友哗戈。也就是說郊艘,陌生的類最好不要作為局部變量的形式出現(xiàn)在類的內(nèi)部。