概述
在工作初期,我們可能會(huì)經(jīng)常會(huì)有這樣的感覺(jué)肩豁,自己的代碼接口設(shè)計(jì)混亂脊串、代碼耦合較為嚴(yán)重辫呻、一個(gè)類(lèi)的代碼過(guò)多等等,自己回頭看的時(shí)候都覺(jué)得汗顏琼锋。再看那些知名的開(kāi)源庫(kù)放闺,它們大多有著整潔的代碼、清晰簡(jiǎn)單的接口缕坎、職責(zé)單一的類(lèi)怖侦,這個(gè)時(shí)候我們通常會(huì)捶胸頓足而感嘆:什么時(shí)候老夫才能寫(xiě)出這樣的代碼!
在做開(kāi)發(fā)的這些年中谜叹,我漸漸的感覺(jué)到匾寝,其實(shí)國(guó)內(nèi)的一些初、中級(jí)工程師寫(xiě)的東西不規(guī)范或者說(shuō)不夠清晰的原因是缺乏一些指導(dǎo)原則荷腊。他們手中揮舞著面向?qū)ο蟮拇笃炱煊酰瑢?xiě)出來(lái)的東西卻充斥著面向過(guò)程的氣味。也許是他們不知道有這些原則停局,也許是他們知道但是不能很好運(yùn)用到實(shí)際代碼中很钓,亦或是他們沒(méi)有在實(shí)戰(zhàn)項(xiàng)目中體會(huì)到這些原則能夠帶來(lái)的優(yōu)點(diǎn),以至于他們對(duì)這些原則并沒(méi)有足夠的重視董栽。
熟悉這些原則之后码倦,不會(huì)讓你立即寫(xiě)出優(yōu)秀的代碼,但會(huì)為你的優(yōu)秀代碼之后鋪上了一條道路锭碳,在這些原則的指導(dǎo)下你才能避免陷入一些常見(jiàn)的代碼泥沼袁稽,從而讓你專(zhuān)心寫(xiě)出優(yōu)秀的東西。
(1)單一職責(zé)原則
(2)里氏替換原則
(3)依賴(lài)倒置原則
(4)開(kāi)閉原則
(5)接口隔離原則
(6)迪米特原則
單一職責(zé)原則
簡(jiǎn)述:一個(gè)類(lèi)只負(fù)責(zé)一個(gè)職責(zé)擒抛。
優(yōu)點(diǎn)
- 類(lèi)的復(fù)雜性降低推汽,實(shí)現(xiàn)什么職責(zé)都有清晰明確的定義;
- 可讀性提高歧沪,復(fù)雜性降低歹撒,那當(dāng)然可讀性提高了;
- 可維護(hù)性提高诊胞,可讀性提高暖夭,那當(dāng)然更容易維護(hù)了;
- 變更引起的風(fēng)險(xiǎn)降低撵孤,變更是必不可少的迈着,如果接口的單一職責(zé)做得好,一個(gè)接口修改只對(duì)相應(yīng)的實(shí)現(xiàn)類(lèi)有影響邪码,對(duì)其他的接口無(wú)影響裕菠,這對(duì)系統(tǒng)的擴(kuò)展性、維護(hù)性都有非常大的幫助闭专。
里氏替換原則
簡(jiǎn)述
面向?qū)ο蟮恼Z(yǔ)言的三大特點(diǎn)是繼承奴潘、封裝旧烧、多態(tài),里氏替換原則就是依賴(lài)于繼承萤彩、多態(tài)這兩大特性粪滤。里氏替換原則簡(jiǎn)單來(lái)說(shuō)就是所有引用基類(lèi)的地方必須能透明地使用其子類(lèi)的對(duì)象斧拍。通俗點(diǎn)講雀扶,只要父類(lèi)能出現(xiàn)的地方子類(lèi)就可以出現(xiàn),而且替換為子類(lèi)也不會(huì)產(chǎn)生任何錯(cuò)誤或異常肆汹,使用者可能根本就不需要知道是父類(lèi)還是子類(lèi)愚墓。但是,反過(guò)來(lái)就不行了昂勉,有子類(lèi)出現(xiàn)的地方浪册,父類(lèi)未必就能適應(yīng)。
優(yōu)點(diǎn)
- 代碼共享岗照,減少創(chuàng)建類(lèi)的工作量村象,每個(gè)子類(lèi)都擁有父類(lèi)的方法和屬性;
- 提高代碼的重用性攒至;
- 提高代碼的可擴(kuò)展性厚者,實(shí)現(xiàn)父類(lèi)的方法就可以“為所欲為”了,很多開(kāi)源框架的擴(kuò)展接口都是通過(guò)繼承父類(lèi)來(lái)完成的迫吐;
- 提高產(chǎn)品或項(xiàng)目的開(kāi)放性库菲。
依賴(lài)倒置原則
簡(jiǎn)述
依賴(lài)倒置原則這個(gè)名字看著有點(diǎn)不好理解,“依賴(lài)”還要“倒置”志膀,這到底是什么意思熙宇?
依賴(lài)倒置原則的幾個(gè)關(guān)鍵點(diǎn)如下:
- 高層模塊不應(yīng)該依賴(lài)低層模塊,兩者都應(yīng)該依賴(lài)其抽象溉浙;
- 抽象不應(yīng)該依賴(lài)細(xì)節(jié)烫止;
- 細(xì)節(jié)應(yīng)該依賴(lài)抽象。
在Java語(yǔ)言中戳稽,抽象就是指接口或抽象類(lèi)烈拒,兩者都是不能直接被實(shí)例化的;細(xì)節(jié)就是實(shí)現(xiàn)類(lèi)广鳍,實(shí)現(xiàn)接口或繼承抽象類(lèi)而產(chǎn)生的類(lèi)就是細(xì)節(jié)荆几,其特點(diǎn)就是可以直接被實(shí)例化,也就是可以加上一個(gè)關(guān)鍵字 new 產(chǎn)生一個(gè)對(duì)象赊时。依賴(lài)倒置原則在 Java 語(yǔ)言中的表現(xiàn)就是:模塊間的依賴(lài)通過(guò)抽象發(fā)生吨铸,實(shí)現(xiàn)類(lèi)之間不發(fā)生直接的依賴(lài)關(guān)系,其依賴(lài)關(guān)系是通過(guò)接口或抽象類(lèi)產(chǎn)生的祖秒。軟件先驅(qū)們總是喜歡將一些理論定義得很抽象诞吱,弄得神不楞登的舟奠,其實(shí)就是一句話:面向接口編程,或者說(shuō)是面向抽象編程房维,這里的抽象指的是接口或者抽象類(lèi)沼瘫。面向接口編程是面向?qū)ο缶柚弧?/p>
優(yōu)點(diǎn)
- 可擴(kuò)展性好;
- 耦合度低咙俩;
開(kāi)閉原則
簡(jiǎn)述
開(kāi)閉原則是 Java 世界里最基礎(chǔ)的設(shè)計(jì)原則耿戚,它指導(dǎo)我們?nèi)绾谓⒁粋€(gè)穩(wěn)定的、靈活的系統(tǒng)阿趁。開(kāi)閉原則的定義是 : 一個(gè)軟件實(shí)體如類(lèi)膜蛔、模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉脖阵。在軟件的生命周期內(nèi)皂股,因?yàn)樽兓⑸?jí)和維護(hù)等原因需要對(duì)軟件原有代碼進(jìn)行修改時(shí)命黔,可能會(huì)給舊代碼中引入錯(cuò)誤呜呐。因此當(dāng)軟件需要變化時(shí),我們應(yīng)該盡量通過(guò)擴(kuò)展的方式來(lái)實(shí)現(xiàn)變化悍募,而不是通過(guò)修改已有的代碼來(lái)實(shí)現(xiàn)蘑辑。
在軟件開(kāi)發(fā)過(guò)程中,永遠(yuǎn)不變的就是變化搜立。開(kāi)閉原則是使我們的軟件系統(tǒng)擁抱變化的核心原則之一以躯。對(duì)擴(kuò)展可放,對(duì)修改關(guān)閉給出了高層次的概括啄踊,即在需要對(duì)軟件進(jìn)行升級(jí)忧设、變化時(shí)應(yīng)該通過(guò)擴(kuò)展的形式來(lái)實(shí)現(xiàn),而非修改原有代碼颠通。當(dāng)然這只是一種比較理想的狀態(tài)址晕,是通過(guò)擴(kuò)展還是通過(guò)修改舊代碼需要根據(jù)代碼自身來(lái)定。
優(yōu)點(diǎn)
- 增加穩(wěn)定性顿锰;
- 可擴(kuò)展性高谨垃。
接口隔離原則
簡(jiǎn)述
客戶(hù)端不應(yīng)該依賴(lài)它不需要的接口;一個(gè)類(lèi)對(duì)另一個(gè)類(lèi)的依賴(lài)應(yīng)該建立在最小的接口上硼控。根據(jù)接口隔離原則刘陶,當(dāng)一個(gè)接口太大時(shí),我們需要將它分割成一些更細(xì)小的接口牢撼,使用該接口的客戶(hù)端僅需知道與之相關(guān)的方法即可匙隔。
優(yōu)點(diǎn)
- 降低耦合性;
- 提升代碼的可讀性熏版;
- 隱藏實(shí)現(xiàn)細(xì)節(jié)纷责。
迪米特原則
簡(jiǎn)述
迪米特法則也稱(chēng)為最少知識(shí)原則(Least Knowledge Principle)捍掺,雖然名字不同,但描述的是同一個(gè)原則:一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有最少的了解再膳。通俗地講挺勿,一個(gè)類(lèi)應(yīng)該對(duì)自己需要耦合或調(diào)用的類(lèi)知道得最少,這有點(diǎn)類(lèi)似接口隔離原則中的最小接口的概念喂柒。類(lèi)的內(nèi)部如何實(shí)現(xiàn)不瓶、如何復(fù)雜都與調(diào)用者或者依賴(lài)者沒(méi)關(guān)系,調(diào)用者或者依賴(lài)者只需要知道他需要的方法即可胳喷,其他的我一概不關(guān)心湃番。類(lèi)與類(lèi)之間的關(guān)系越密切夭织,耦合度越大吭露,當(dāng)一個(gè)類(lèi)發(fā)生改變時(shí),對(duì)另一個(gè)類(lèi)的影響也越大尊惰。
迪米特法則還有一個(gè)英文解釋是: Only talk to your immedate friends( 只與直接的朋友通信讲竿。)什么叫做直接的朋友呢?每個(gè)對(duì)象都必然會(huì)與其他對(duì)象有耦合關(guān)系弄屡,兩個(gè)對(duì)象之間的耦合就成為朋友關(guān)系题禀,這種關(guān)系的類(lèi)型有很多,例如組合膀捷、聚合迈嘹、依賴(lài)等。
總結(jié)一句話:盡量少的知道對(duì)象的信息全庸,只與直接的朋友交互秀仲。
優(yōu)點(diǎn)
- 降低復(fù)雜度;
- 降低耦合度壶笼;
- 增加穩(wěn)定性神僵。
總結(jié):
面向?qū)ο罅笤瓌t在開(kāi)發(fā)過(guò)程中極為重要,如果能夠很好地將這些原則運(yùn)用到項(xiàng)目中覆劈,再在一些合適的場(chǎng)景運(yùn)用一些前人驗(yàn)證過(guò)的模式保礼,那么開(kāi)發(fā)出來(lái)的軟件在一定程度上能夠得到質(zhì)量保證。其實(shí)稍微一想责语,這幾大原則最終就化為這么幾個(gè)關(guān)鍵詞: 抽象炮障、單一職責(zé)、最小化坤候。那么在實(shí)際開(kāi)發(fā)過(guò)程中如何權(quán)衡胁赢、實(shí)踐這些原則,筆者也在不斷地學(xué)習(xí)铐拐、摸索徘键。我想學(xué)習(xí)任何的事物莫過(guò)于實(shí)踐练对、經(jīng)驗(yàn)與領(lǐng)悟,在這個(gè)過(guò)程中希望能夠與大家分享知識(shí)吹害、共同進(jìn)步螟凭。