一天吓、開閉原則(Open-Closed Principle, OCP):是總綱贿肩,要對擴(kuò)展開放,對修改關(guān)閉
二龄寞、單一職責(zé)原則(Single Responsibility Principle汰规,SRP):實(shí)現(xiàn)類要職責(zé)單一
三、里氏代換原則(Liskov Substitution Principle, LSP):不要破壞繼承體系
四物邑、依賴倒置原則(Dependence Inversion Principle溜哮,DIP):要面向接口編程
五滔金、接口隔離原則(Interface Segregation Principle, ISP):在設(shè)計(jì)接口的時(shí)候要精簡單一
六、迪米特法則(Law of Demeter, LoD):又叫最少知識原則(Least Knowledge Principle茂嗓,LKP)餐茵,只跟朋友交流,不跟陌生人說話述吸,要降低耦合
一忿族、開閉原則 OCP(Open-Closed Principle)
定義
一個(gè)軟件實(shí)體應(yīng)當(dāng)對擴(kuò)展開放,對修改關(guān)閉蝌矛。即軟件實(shí)體應(yīng)盡量在不修改原有代碼的情況下進(jìn)行擴(kuò)展
實(shí)現(xiàn)
為了滿足開閉原則道批,需要對系統(tǒng)進(jìn)行抽象化設(shè)計(jì),抽象化是開閉原則的關(guān)鍵入撒。在Java屹徘、C#等編程語言中,可以為系統(tǒng)定義一個(gè)相對穩(wěn)定的抽象層衅金,而將不同的實(shí)現(xiàn)行為移至具體的實(shí)現(xiàn)層中完成噪伊。如果需要修改系統(tǒng)的行為,無須對抽象層進(jìn)行任何改動(dòng)氮唯,只需要增加新的具體類來實(shí)現(xiàn)新的業(yè)務(wù)功能即可鉴吹,實(shí)現(xiàn)在不修改已有代碼的基礎(chǔ)上擴(kuò)展系統(tǒng)的功能,達(dá)到開閉原則的要求惩琉。
開閉原則優(yōu)點(diǎn)
- 開閉原則是最基礎(chǔ)的設(shè)計(jì)原則豆励,其它的五個(gè)設(shè)計(jì)原則都是開閉原則的具體形態(tài),也就是說其它的五個(gè)設(shè)計(jì)原則是指導(dǎo)設(shè)計(jì)的工具和方法瞒渠,而開閉原則才是其精神領(lǐng)袖良蒸。依照J(rèn)ava語言的稱謂,開閉原則是抽象類伍玖,而其它的五個(gè)原則是具體的實(shí)現(xiàn)類嫩痰。
- 開閉原則可以提高復(fù)用性
- 開閉原則可以提高維護(hù)性
- 面向?qū)ο箝_發(fā)的要求
二、單一職責(zé)原則 SRP(Single Responsibility Principle)
定義:
一個(gè)類只負(fù)責(zé)一個(gè)功能領(lǐng)域中的相應(yīng)職責(zé)窍箍,或者可以定義為:就一個(gè)類而言串纺,應(yīng)該只有一個(gè)引起它變化的原因。
思想:
如果一個(gè)類承擔(dān)的職責(zé)過多椰棘,就等于把這些職責(zé)耦合在一起纺棺,一個(gè)職責(zé)的變化可能會(huì)削弱或者抑制這個(gè)類完成其他職責(zé)的能力。這種耦合會(huì)導(dǎo)致脆弱的設(shè)計(jì)邪狞,當(dāng)變化發(fā)生時(shí)祷蝌,設(shè)計(jì)會(huì)遭受到意想不到的破壞。單一職責(zé)原則是實(shí)現(xiàn)高內(nèi)聚帆卓、低耦合的指導(dǎo)方針巨朦。
單一職責(zé)原的優(yōu)點(diǎn):
- 可以降低類的復(fù)雜度乡翅,一個(gè)類只負(fù)責(zé)一項(xiàng)職責(zé),其邏輯肯定要比負(fù)責(zé)多項(xiàng)職責(zé)簡單的多罪郊;
- 提高類的可讀性,提高系統(tǒng)的可維護(hù)性尚洽;
- 變更引起的風(fēng)險(xiǎn)降低悔橄,變更是必然的,如果單一職責(zé)原則遵守的好腺毫,當(dāng)修改一個(gè)功能時(shí)癣疟,可以顯著降低對其他功能的影響。
三潮酒、里氏代換原則 LSP(Liskov Substitution Principle)
定義
所有引用基類(父類)的地方必須能透明地使用其子類的對象睛挚。LSP是繼承復(fù)用的基石。
繼承優(yōu)點(diǎn)
- 代碼共享急黎,減少創(chuàng)建類的工作量扎狱,每個(gè)子類都擁有父類的方法和屬性;
- 提高代碼的重用性勃教;子類可以形似父類淤击,但又異于父類;
- 提高代碼的可擴(kuò)展性故源,實(shí)現(xiàn)父類的方法就可以“為所欲為”了;提高產(chǎn)品或項(xiàng)目的開放性污抬。
繼承缺點(diǎn)
- 繼承是侵入性的。只要繼承绳军,就必須擁有父類的所有屬性和方法印机;
- 降低代碼的靈活性。子類必須擁有父類的屬性和方法门驾;
- 增強(qiáng)了耦合性射赛。當(dāng)父類的常量、變量和方法被修改時(shí)奶是,必需要考慮子類的修改咒劲,而且在缺乏規(guī)范的環(huán)境下,這種修改可能帶來非常糟糕的結(jié)果:大片的代碼需要重構(gòu)诫隅。
克服繼承的缺點(diǎn)——里氏代換原則
里氏代換原則是對“開-閉”原則的補(bǔ)充腐魂。實(shí)現(xiàn)“開-閉”原則的關(guān)鍵步驟就是抽象化。而基類與子類的繼承關(guān)系就是抽象化的具體實(shí)現(xiàn)逐纬,所以里氏代換原則是對實(shí)現(xiàn)抽象化的具體步驟的規(guī)范蛔屹。
注意事項(xiàng)
- 子類的所有方法必須在父類中聲明,或子類必須實(shí)現(xiàn)父類中聲明的所有方法豁生。根據(jù)里氏代換原則兔毒,為了保證系統(tǒng)的擴(kuò)展性漫贞,在程序中通常使用父類來進(jìn)行定義,如果一個(gè)方法只存在子類中育叁,在父類中不提供相應(yīng)的聲明迅脐,則無法在以父類定義的對象中使用該方法。
- 我們在運(yùn)用里氏代換原則時(shí)豪嗽,盡量把父類設(shè)計(jì)為抽象類或者接口谴蔑,讓子類繼承父類或?qū)崿F(xiàn)父接口,并實(shí)現(xiàn)在父類中聲明的方法龟梦,運(yùn)行時(shí)隐锭,子類實(shí)例替換父類實(shí)例,我們可以很方便地?cái)U(kuò)展系統(tǒng)的功能计贰,同時(shí)無須修改原有子類的代碼钦睡,增加新的功能可以通過增加一個(gè)新的子類來實(shí)現(xiàn)。里氏代換原則是開閉原則的具體實(shí)現(xiàn)手段之一躁倒。
- Java語言中荞怒,在編譯階段,Java編譯器會(huì)檢查一個(gè)程序是否符合里氏代換原則秧秉,這是一個(gè)與實(shí)現(xiàn)無關(guān)的挣输、純語法意義上的檢查,但Java編譯器的檢查是有局限的
四福贞、依賴倒置原則 DIP(Dependence Inversion Principle)
定義
高層模塊不應(yīng)該依賴低層模塊撩嚼,兩者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細(xì)節(jié)挖帘,細(xì)節(jié)應(yīng)該依賴抽象完丽,其核心思想是:要面向接口編程,不要面向?qū)崿F(xiàn)編程拇舀。
作用
- 降低類間的耦合性逻族。
- 提高系統(tǒng)的穩(wěn)定性。
- 減少并行開發(fā)引起的風(fēng)險(xiǎn)骄崩。
- 提高代碼的可讀性和可維護(hù)性聘鳞。
實(shí)現(xiàn)方法
- 每個(gè)類盡量提供接口或抽象類,或者兩者都具備要拂。
- 變量的聲明類型盡量是接口或者是抽象類抠璃。
- 任何類都不應(yīng)該從具體類派生。
- 使用繼承時(shí)盡量遵循里氏替換原則
五脱惰、接口隔離原則 ISP(Interface Segregation Principle)
定義
使用多個(gè)專門的接口搏嗡,而不使用單一的總接口,即客戶端不應(yīng)該依賴那些它不需要的接口。
接口隔離原則和單一職責(zé)都是為了提高類的內(nèi)聚性采盒、降低它們之間的耦合性旧乞,體現(xiàn)了封裝的思想,但兩者是不同的:
- 單一職責(zé)原則注重的是職責(zé)磅氨;而接口隔離原則注重的是對接口依賴的隔離尺栖。
- 單一職責(zé)原則主要是約束類,它針對的是程序中的實(shí)現(xiàn)和細(xì)節(jié)烦租;接口隔離原則主要約束接口延赌,主要針對抽象和程序整體框架的構(gòu)建。
優(yōu)點(diǎn)
- 多個(gè)粒度小的接口左权,可以預(yù)防外來變更的擴(kuò)散,提高系統(tǒng)的靈活性和可維護(hù)性痴颊。
- 提高了系統(tǒng)的內(nèi)聚性赏迟,減少了對外交互,降低了系統(tǒng)的耦合性蠢棱。
- 合理粒度大小的接口锌杀,能夠保證系統(tǒng)的穩(wěn)定性
- 使用多個(gè)專門的接口還能夠體現(xiàn)對象的層次
- 能減少項(xiàng)目工程中的代碼冗余
實(shí)現(xiàn)方法
- 接口盡量小,但是要有限度泻仙。一個(gè)接口只服務(wù)于一個(gè)子模塊或業(yè)務(wù)邏輯糕再。
- 為依賴接口的類定制服務(wù)。只提供調(diào)用者需要的方法玉转,屏蔽不需要的方法突想。
- 了解環(huán)境,拒絕盲從究抓。每個(gè)項(xiàng)目或產(chǎn)品都有選定的環(huán)境因素猾担,環(huán)境不同,接口拆分的標(biāo)準(zhǔn)就不同深入了解業(yè)務(wù)邏輯刺下。
- 提高內(nèi)聚绑嘹,減少對外交互。使接口用最少的方法去完成最多的事情橘茉。
六工腋、迪米特法則 LoD(Law of Demeter)
定義
一個(gè)軟件實(shí)體應(yīng)當(dāng)盡可能少地與其他實(shí)體發(fā)生相互作用。
迪米特法則又叫作最少知識原則 LKP(Least Knowledge Principle)畅卓,產(chǎn)生于 1987 年美國東北大學(xué)(Northeastern University)的一個(gè)名為迪米特(Demeter)的研究項(xiàng)目擅腰,由伊恩·荷蘭(Ian Holland)提出,被 UML 創(chuàng)始者之一的布奇(Booch)普及翁潘,后來又因?yàn)樵诮?jīng)典著作《程序員修煉之道》(The Pragmatic Programmer)提及而廣為人知惕鼓。
迪米特法則的定義是:只與你的直接朋友交談,不跟“陌生人”說話(Talk only to your immediate friends and not to strangers)唐础。其含義是:如果兩個(gè)軟件實(shí)體無須直接通信箱歧,那么就不應(yīng)當(dāng)發(fā)生直接的相互調(diào)用矾飞,可以通過第三方轉(zhuǎn)發(fā)該調(diào)用。其目的是降低類之間的耦合度呀邢,提高模塊的相對獨(dú)立性洒沦。
迪米特法則中的“朋友”是指:當(dāng)前對象本身、當(dāng)前對象的成員對象价淌、當(dāng)前對象所創(chuàng)建的對象申眼、當(dāng)前對象的方法參數(shù)等,這些對象同當(dāng)前對象存在關(guān)聯(lián)蝉衣、聚合或組合關(guān)系括尸,可以直接訪問這些對象的方法。
優(yōu)點(diǎn)
- 降低了類之間的耦合度病毡,提高了模塊的相對獨(dú)立性濒翻。
- 由于親合度降低,從而提高了類的可復(fù)用率和系統(tǒng)的擴(kuò)展性啦膜。
缺點(diǎn)
但是有送,過度使用迪米特法則會(huì)使系統(tǒng)產(chǎn)生大量的中介類,從而增加系統(tǒng)的復(fù)雜性僧家,使模塊之間的通信效率降低雀摘。所以,在釆用迪米特法則時(shí)需要反復(fù)權(quán)衡八拱,確保高內(nèi)聚和低耦合的同時(shí)阵赠,保證系統(tǒng)的結(jié)構(gòu)清晰
實(shí)現(xiàn)
- 在類的劃分上,應(yīng)該創(chuàng)建弱耦合的類肌稻。類與類之間的耦合越弱豌注,就越有利于實(shí)現(xiàn)可復(fù)用的目標(biāo)。
- 在類的結(jié)構(gòu)設(shè)計(jì)上灯萍,盡量降低類成員的訪問權(quán)限轧铁。
- 在類的設(shè)計(jì)上,優(yōu)先考慮將一個(gè)類設(shè)置成不變類旦棉。
- 在對其他類的引用上齿风,將引用其他對象的次數(shù)降到最低。
- 不暴露類的屬性成員绑洛,而應(yīng)該提供相應(yīng)的訪問器(set 和 get 方法)救斑。
- 謹(jǐn)慎使用序列化(Serializable)功能。