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

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

閱讀目錄

內(nèi)容總覽

六大設(shè)計(jì)原則都有哪些

一、單一職責(zé)原則
二般婆、里氏替換原則
三枢里、依賴倒置原則
四、接口隔離原則
五狡赐、迪米特法則
六、開(kāi)放封閉原則

內(nèi)容詳解

一钦幔、單一職責(zé)原則

單一職責(zé)原則:英文名稱是Single Responsiblity Principle枕屉,簡(jiǎn)稱是SRP。定義:應(yīng)該有且僅有一個(gè)原因引起類的變更鲤氢。

單一職責(zé)原則要求:一個(gè)接口或類只有一個(gè)原因引起變化搀擂,也就是一個(gè)接口或類只有一個(gè)職責(zé)西潘,它就負(fù)責(zé)一件事情。

單一職責(zé)原則的好處:

  1. 類的復(fù)雜性降低哨颂,實(shí)現(xiàn)什么職責(zé)都有清晰明確的定義喷市;
  2. 可讀性提高,復(fù)雜性降低威恼,那當(dāng)然可讀性提高了品姓;
  3. 可維護(hù)性提高,可讀性提高箫措,那當(dāng)然更容易維護(hù)了腹备;
  4. 變更引起的風(fēng)險(xiǎn)降低,變更是必不可少的斤蔓,如果接口的單一職責(zé)做得好植酥,一個(gè)接口修改只對(duì)相應(yīng)的實(shí)現(xiàn)類有影響,對(duì)其他的接口無(wú)影響弦牡,這對(duì)系統(tǒng)的擴(kuò)展性友驮、維護(hù)性都有非常大的幫助。

注意: 單一職責(zé)原則提出了一個(gè)編寫程序的標(biāo)準(zhǔn)驾锰,用“職責(zé)”或“變化原因”來(lái)衡量接口或類設(shè)計(jì)得是否優(yōu)良卸留,但是“職責(zé)”和“變化原因”都是不可度量的,因項(xiàng)目而異稻据,因環(huán)境而異艾猜。

對(duì)于單一職責(zé)原則,接口一定要做到單一職責(zé)捻悯,類的設(shè)計(jì)盡量做到只有一個(gè)原因引起變化匆赃。

二、里氏替換原則

里氏替換原則(Liskov Substitution Principle今缚,LSP)算柳,有兩種定義:

  • 第一種定義,也是最正宗的定義:If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T ,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.(如果對(duì)每一個(gè)類型為S的對(duì)象o1姓言,都有類型為T的對(duì)象o2瞬项,使得以T定義的所有程序P在所有的對(duì)象o1都代換成o2時(shí),程序P的行為沒(méi)有發(fā)生變化何荚,那么類型S是類型T的子類型囱淋。)
  • 第二種定義:Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.(所有引用基類的地方必須能透明地使用其子類的對(duì)象。)

第二個(gè)定義是最清晰明確的餐塘,通俗點(diǎn)講妥衣,只要父類出現(xiàn)的地方子類就可以出現(xiàn),而且替換為子類也不會(huì)產(chǎn)生任何錯(cuò)誤或異常,使用者可能根本就不需要知道父類還是子類税手。但是反過(guò)來(lái)就不行了蜂筹,有子類出現(xiàn)的地方,父類未必就能適應(yīng)芦倒。

里氏替換原則為良好的繼承定義了一個(gè)規(guī)范艺挪,一句簡(jiǎn)單的定義包含了4層含義:

  1. 子類必須完全實(shí)現(xiàn)父類的方法;

    1. 在類中調(diào)用其他類時(shí)務(wù)必要使用父類或接口兵扬,如果不能使用父類或接口麻裳,則說(shuō)明類的設(shè)計(jì)已經(jīng)違背了LSP原則;
    2. 如果子類不能完整地實(shí)現(xiàn)父類的方法周霉,或者父類的某些方法在子類中已經(jīng)發(fā)生“畸變”掂器,則建議斷開(kāi)父子繼承關(guān)系,采用依賴俱箱、聚集、組合等關(guān)系代替繼承灭必。
  2. 子類可以有自己的個(gè)性狞谱;

  3. 覆蓋或?qū)崿F(xiàn)父類的方法時(shí)輸入?yún)?shù)可以被放大;

    1. 如果父類的輸入?yún)?shù)類型大于子類的輸入?yún)?shù)類型禁漓,會(huì)出現(xiàn)父類存在的地方跟衅,子類未必會(huì)存在,因?yàn)橐坏┌炎宇愖鳛閰?shù)傳入播歼,調(diào)用者很可能進(jìn)入子類的方法范疇伶跷;
    2. 子類中方法的前置條件必須與超類中被覆寫的方法的前置條件相同或者更寬松。
  4. 覆寫或?qū)崿F(xiàn)父類的方法時(shí)輸出結(jié)果可以被縮小秘狞。

    1. 父類的一個(gè)方法的返回值是一個(gè)類型T叭莫,子類的相同方法(重載或覆寫)的返回值為S,那么里氏替換原則就要求S必須小于等于T烁试,也就是說(shuō)雇初,要么S和T是同一個(gè)類型,要么S是T的子類减响。

采用里氏替換原則的目的就是增強(qiáng)程序的健壯性靖诗,版本升級(jí)時(shí)也可以保持非常好的兼容性。即使增加子類支示,原有的子類還可以繼續(xù)執(zhí)行刊橘。

三、依賴倒置原則

依賴倒置原則(Dependence Inversion Principle,DIP),原始定義是:High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.

包含三層含義:

  1. 高層模塊不應(yīng)該依賴底層模塊颂鸿,兩者都應(yīng)該依賴抽象促绵;
  2. 抽象不應(yīng)該依賴細(xì)節(jié);
  3. 細(xì)節(jié)應(yīng)該依賴抽象。

高層模塊和低層模塊容易理解绞愚,每一個(gè)邏輯的實(shí)現(xiàn)都是由原子邏輯組成的叙甸,不可分割的原子邏輯就是底層模塊,原子邏輯的再組裝就是高層模塊位衩。

在Java語(yǔ)言中裆蒸,抽象就是指接口或抽象類,兩者都是不能直接被實(shí)例化的糖驴;細(xì)節(jié)就是實(shí)現(xiàn)類僚祷,實(shí)現(xiàn)接口或繼承抽象類而產(chǎn)生的類就是細(xì)節(jié),其特點(diǎn)就是可以直接被實(shí)例化贮缕,也就是可以加上一個(gè)關(guān)鍵字new產(chǎn)生一個(gè)對(duì)象辙谜。依賴倒置原則在Java語(yǔ)言中的表現(xiàn)就是:

  1. 模塊間的依賴通過(guò)抽象發(fā)生,實(shí)現(xiàn)類之間不發(fā)生直接的依賴關(guān)系感昼,其依賴關(guān)系是通過(guò)接口或抽象類產(chǎn)生的装哆;
  2. 接口或抽象類不依賴于實(shí)現(xiàn)類;
  3. 實(shí)現(xiàn)類依賴接口或抽象類定嗓。

更加精簡(jiǎn)的定義就是“面向接口編程”--OOD(Object-Oriented Design蜕琴,面向?qū)ο笤O(shè)計(jì))的精髓之一。

依賴的三種寫法:

依賴是可以傳遞的宵溅,A對(duì)象依賴B對(duì)象凌简,B又依賴C,C又依賴D恃逻。雏搂。。寇损。凸郑。。生生不息润绵,依賴不止线椰,記住一點(diǎn):只要做到抽象依賴,即使是多層的依賴傳遞也無(wú)所畏懼尘盼!

對(duì)象的依賴關(guān)系有三種方式來(lái)傳遞:

  1. 構(gòu)造函數(shù)傳遞依賴對(duì)象 --- 在類中通過(guò)構(gòu)造函數(shù)聲明依賴對(duì)象憨愉,按照依賴注入的說(shuō)法,這種方式叫做構(gòu)造函數(shù)注入卿捎。
  2. Setter方法傳遞依賴對(duì)象 --- 在抽象中設(shè)置Setter方法聲明依賴關(guān)系配紫,依照注入的說(shuō)法,這是Setter依賴注入午阵。
  3. 在接口的方法中聲明依賴對(duì)象躺孝,這種方式也叫做接口注入享扔。

依賴倒置原則的本質(zhì)就是通過(guò)抽象(接口或抽象類)使各個(gè)類或模塊的實(shí)現(xiàn)彼此獨(dú)立,不互相影響植袍,實(shí)現(xiàn)模塊間的松耦合惧眠,我們?cè)趺丛陧?xiàng)目中使用這個(gè)規(guī)則呢?只要遵循以下的規(guī)則就可以:

  1. 每個(gè)類盡量都有接口或抽象類于个,或者抽象類和接口兩者都具備氛魁; --- 這是依賴倒置的基本要求,接口或抽象類都是屬于抽象的厅篓,有了抽象才可能依賴倒置秀存。
  2. 變量的表面類型盡量是接口或者是抽象類;
  3. 任何類都不應(yīng)該從具體類派生羽氮;
  4. 盡量不要覆寫基類的方法或链; --- 如果基類是一個(gè)抽象類,而且這個(gè)方法已經(jīng)實(shí)現(xiàn)了档押,子類盡量不要覆寫澳盐。類間依賴的是抽象,覆寫了抽象方法汇荐,對(duì)依賴的穩(wěn)定性會(huì)產(chǎn)生一定的影響洞就。
  5. 結(jié)合里氏替換原則使用。 --- 接口負(fù)責(zé)定義public屬性和方法掀淘,并且聲明與其他對(duì)象的依賴關(guān)系,抽象類負(fù)責(zé)公共構(gòu)造部分的實(shí)現(xiàn)油昂,實(shí)現(xiàn)類準(zhǔn)確的實(shí)現(xiàn)業(yè)務(wù)邏輯革娄,同時(shí)在適當(dāng)?shù)臅r(shí)候?qū)Ω割愡M(jìn)行細(xì)化。

四冕碟、接口隔離原則

接口分為兩種:

  1. 實(shí)例接口(Object Interface)拦惋,在Java中聲明一個(gè)類,然后用new關(guān)鍵字產(chǎn)生一個(gè)實(shí)例安寺,它是對(duì)一個(gè)類型的食物的描述厕妖,這是一種接口。
  2. 類接口(Class Interface)挑庶,Java中經(jīng)常使用的interface關(guān)鍵字定義的接口言秸;
  3. Clients should not be forced to depend upon interfaces that they don‘t use。(客戶端不應(yīng)該依賴它不需要的接口迎捺。)
  4. The dependency of one class to another one should depend on the smallest possible interface举畸。(類間的依賴關(guān)系應(yīng)該建立在最小的接口上。)

接口隔離原則是對(duì)接口進(jìn)行規(guī)范約束凳枝,其包含以下4層含義:

  1. 接口要盡量谐凇; --- 這是接口隔離原則的核心定義,不出現(xiàn)臃腫的接口(Fat Interface)叛买,但是“小”是有限度的砂代,首先就是不能違反單一職責(zé)原則。
  2. 接口要高內(nèi)聚率挣; --- 高內(nèi)聚就是提高接口刻伊、類、模塊的處理能力难礼,減少對(duì)外的交互娃圆。在接口中盡量少公布public方法,接口是對(duì)外的承諾蛾茉,承諾越少對(duì)系統(tǒng)的開(kāi)發(fā)越有利讼呢,變更的風(fēng)險(xiǎn)也就越少,同時(shí)也越有利于降低成本谦炬。
  3. 定制服務(wù)悦屏; --- 一個(gè)系統(tǒng)或系統(tǒng)內(nèi)的模塊之間必然會(huì)有耦合,有耦合就要有相互訪問(wèn)的接口(并不一定就是Java中定義的Interface键思,也可能是一個(gè)類或單純的數(shù)據(jù)交換)础爬,我們?cè)O(shè)計(jì)時(shí)就需要為各個(gè)訪問(wèn)者(即客戶端)定制服務(wù)。定制服務(wù)就是單獨(dú)為一個(gè)個(gè)體提供優(yōu)良的服務(wù)吼鳞。我們?cè)谧鱿到y(tǒng)設(shè)計(jì)時(shí)也需要考慮對(duì)系統(tǒng)之間或模塊之間的接口采用定制服務(wù)看蚜。采用定制服務(wù)就必然有一個(gè)要求:只提供訪問(wèn)者需要的方法。
  4. 接口設(shè)計(jì)是有限度的赔桌。 --- 接口的設(shè)計(jì)粒度越小供炎,系統(tǒng)越靈活,這是不爭(zhēng)的事實(shí)疾党。但是音诫,靈活的同時(shí)也帶來(lái)了結(jié)構(gòu)的復(fù)雜化,開(kāi)發(fā)難度增加雪位,可維護(hù)性低竭钝,這不是一個(gè)項(xiàng)目或產(chǎn)品所期望看到的,所以接口設(shè)計(jì)一定要注意適度雹洗,這個(gè)“度”如何來(lái)判斷香罐?根據(jù)經(jīng)驗(yàn)和常識(shí)判斷,沒(méi)有一個(gè)固話或可測(cè)量的標(biāo)準(zhǔn)队伟。

接口隔離原則是對(duì)接口的定義穴吹,同時(shí)也是對(duì)類的定義,接口和類盡量使用原子接口或原子類來(lái)組裝嗜侮。但是港令,這個(gè)原子該怎么劃分是設(shè)計(jì)模式中的一大難題啥容,在實(shí)踐中可以根據(jù)以下幾個(gè)規(guī)則來(lái)衡量:

  1. 一個(gè)接口只服務(wù)于一個(gè)模塊或業(yè)務(wù)邏輯;
  2. 通過(guò)業(yè)務(wù)邏輯壓縮接口中的public方法顷霹,接口時(shí)常去回顧咪惠,盡量讓接口達(dá)到“滿身筋骨肉”,而不是“肥嘟嘟”的一大堆方法淋淀;
  3. 已經(jīng)被污染了的接口遥昧,盡量去修改,若變更的風(fēng)險(xiǎn)較大朵纷,則采用適配器模式進(jìn)行轉(zhuǎn)化處理炭臭;
  4. 了解環(huán)境,拒絕盲從袍辞。每個(gè)項(xiàng)目或產(chǎn)品都有特定的環(huán)境因素鞋仍,別看到大師是這樣做的你就照抄。千萬(wàn)別搅吁,環(huán)境不同威创,接口拆分的標(biāo)準(zhǔn)就不同。深入了解業(yè)務(wù)邏輯谎懦,最好的接口設(shè)計(jì)就出自你的手中肚豺!

五、迪米特法則

迪米特法則(Law of Demeter 界拦,LoD)也稱為最少知識(shí)原則(Least Knowledge Principle吸申,LKP),雖然名字不同享甸,但描述的是同一個(gè)規(guī)則:一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有最少的了解呛谜。通俗地講,一個(gè)類應(yīng)該對(duì)自己需要耦合或調(diào)用的類知道得最少枪萄,你(被耦合或調(diào)用的類)的內(nèi)部是如何復(fù)雜都和我沒(méi)關(guān)系,那是你的事情猫妙,我就知道你提供的這么多public方法瓷翻,我就調(diào)用這么多,其他的我一概不關(guān)心割坠。

迪米特法則對(duì)類的低耦合提出了明確的要求齐帚,其包含以下4層含義:

  1. 只和朋友交流 --- 迪米特法則還有一個(gè)英文解釋是:Only talk to your immedate friends(只與直接的朋友通信。)什么叫做直接的朋友彼哼?每個(gè)對(duì)象都必然會(huì)與其他對(duì)象有耦合關(guān)系对妄,兩個(gè)對(duì)象之間的耦合就成為朋友關(guān)系,這種關(guān)系的類型有很多敢朱,例如組合剪菱、聚合摩瞎、依賴等。朋友類的定義:出現(xiàn)在成員變量孝常、方法的輸入輸出參數(shù)中的類稱為成員朋友類旗们,而出現(xiàn)在方法體內(nèi)部的類不屬于朋友類。注意:一個(gè)類只和朋友交流构灸,不與陌生類交流上渴,不要出現(xiàn)getA().getB().getC().getD()這種情況(在一種極端的情況下允許出現(xiàn)這種訪問(wèn),即每一個(gè)點(diǎn)后面返回類型都相同)喜颁,類與類之間的關(guān)系是建立在類間的稠氮,而不是方法間,因此一個(gè)方法盡量不引入一個(gè)類中不存在的對(duì)象半开,當(dāng)然隔披,JDK API提供的類除外。
  2. 朋友間也是有距離的 --- 一個(gè)類公開(kāi)的public屬性或方法越多稿茉,修改時(shí)涉及的面積越大锹锰,變更引起的風(fēng)險(xiǎn)擴(kuò)散也就越大。因此漓库,為了保持朋友類間的距離恃慧,在設(shè)計(jì)時(shí)需要反復(fù)衡量:是否還可以再減少public方法和屬性,是否可以修改為private渺蒿、package-private(包類型痢士,在類、方法茂装、變量前不加訪問(wèn)權(quán)限怠蹂,則默認(rèn)為包類型)、protected 等訪問(wèn)權(quán)限少态,是否可以加上final關(guān)鍵字等城侧。 注意:迪米特法則要求類“羞澀”一點(diǎn),盡量不要對(duì)外公布太多的public方法和非靜態(tài)的public變量彼妻,盡量?jī)?nèi)斂嫌佑,多使用private、package-private侨歉、protected等訪問(wèn)權(quán)限屋摇。
  3. 是自己的就是自己的 --- 如果一個(gè)方法放在本類中,即不增加類間的關(guān)系幽邓,也對(duì)本類不產(chǎn)生負(fù)面影響炮温,就放置在本類中。
  4. 謹(jǐn)慎使用Serializable

迪米特法則的核心觀念就是類間解耦牵舵,弱耦合柒啤,只有弱耦合了以后倦挂,類的復(fù)用率才可以提高。其要求的結(jié)果就是產(chǎn)生了大量的中轉(zhuǎn)或跳轉(zhuǎn)類白修,導(dǎo)致系統(tǒng)的復(fù)雜性提高妒峦,同時(shí)也為維護(hù)帶來(lái)了難度。

迪米特法則要求類間解耦兵睛,但解耦是有限度的肯骇,除非是計(jì)算機(jī)的最小單元——二進(jìn)制的0和1。那才是完全解耦祖很,在實(shí)際的項(xiàng)目中笛丙,需要適度地考慮這個(gè)原則,別為了套用原則而做項(xiàng)目假颇。原則只是供參考胚鸯,如果違背了這個(gè)原則,項(xiàng)目也未必會(huì)失敗笨鸡,這就需要大家在采用原則時(shí)反復(fù)度量姜钳,不遵循是不對(duì)的,嚴(yán)格執(zhí)行就是“過(guò)猶不及”形耗。

六哥桥、開(kāi)放封閉原則

開(kāi)放封閉原則的定義:Software entities like classes, modules and functions should be open for extension but closed for modifications.(一個(gè)軟件實(shí)體如類、模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開(kāi)放激涤,對(duì)修改關(guān)閉拟糕。)其含義是說(shuō)一個(gè)軟件實(shí)體應(yīng)該通過(guò)擴(kuò)展來(lái)實(shí)現(xiàn)變化。軟實(shí)體包括以下幾個(gè)部分:

  1. 項(xiàng)目或軟件產(chǎn)品中按照一定的邏輯規(guī)則劃分的模塊倦踢;
  2. 抽象和類送滞;
  3. 方法。

一個(gè)軟件產(chǎn)品只要在生命周期內(nèi)辱挥,都會(huì)發(fā)生變化犁嗅,既然變化是一個(gè)既定的事實(shí),我們就應(yīng)該在設(shè)計(jì)時(shí)盡量適應(yīng)這些變化晤碘,以提高項(xiàng)目的穩(wěn)定性和靈活性愧哟,真正實(shí)現(xiàn)“擁抱變化”。開(kāi)放封閉原則告訴我們應(yīng)盡量通過(guò)擴(kuò)展軟件實(shí)體的行為來(lái)實(shí)現(xiàn)變化哼蛆,而不是通過(guò)修改已有的代碼來(lái)完成變化,它是為軟件實(shí)體的未來(lái)事件而制定的對(duì)現(xiàn)行開(kāi)發(fā)設(shè)計(jì)進(jìn)行約束的一個(gè)原則霞赫。

開(kāi)放封閉原則對(duì)擴(kuò)展開(kāi)放腮介,對(duì)修改封閉,并不意味著不做任何修改端衰,低層模塊的變更叠洗,必然要有高層模塊進(jìn)行耦合甘改,否則就是一個(gè)孤立無(wú)意義的代碼片段。我們可以把變化歸納以下三種類型:

  1. 邏輯變化灭抑; -- 只變化一個(gè)邏輯十艾,而不涉及其他模塊,比如原有的一個(gè)算法是 ab+c 腾节,現(xiàn)在需要修改為 ab*c 忘嫉,可以通過(guò)修改原有類中的方法的方式來(lái)完成,前提條件是所有依賴關(guān)系都按照相同的邏輯處理案腺。
  2. 子模塊變化庆冕; ---一個(gè)模塊變化,會(huì)對(duì)其他的模塊產(chǎn)生影響劈榨,特別是一個(gè)低層次的模塊變化必然引起高層次模塊的變化访递,因此在通過(guò)擴(kuò)展完成變化時(shí),高層次的模塊修改是必然的同辣。
  3. 可見(jiàn)視圖變化 --- 可見(jiàn)視圖是提供給客戶使用的界面拷姿,如JSP程序、Swing界面等旱函,該部分的變化一般會(huì)引起連鎖反應(yīng)(特別是在國(guó)內(nèi)做項(xiàng)目响巢,做歐美的外包項(xiàng)目一般不會(huì)影響太大)。如果僅僅是界面上按鈕陡舅、文字的重新排列倒是簡(jiǎn)單抵乓,最司空見(jiàn)慣的是業(yè)務(wù)耦合變化,什么意思靶衍?一個(gè)展示數(shù)據(jù)的列表灾炭,按照原有的需求是6列,突然有一天要增加1列颅眶,而且這一列要跨N張表蜈出,處理M個(gè)邏輯才能展現(xiàn)出來(lái),這樣的變化是比較恐怖的涛酗,但還是可以通過(guò)擴(kuò)展來(lái)完成變化铡原,這就要看我們?cè)械脑O(shè)計(jì)是否靈活。

為什么要采用開(kāi)放封閉原則:

每個(gè)事物的誕生都有它存在的必要性商叹,存在即合理燕刻,那開(kāi)閉原則的存在也是合理的,為什么這么說(shuō)呢剖笙?

首先卵洗,開(kāi)閉原則是那么地著名,只要是做面向?qū)ο缶幊痰拿诌洌鹿苁鞘裁凑Z(yǔ)言过蹂,Java也好十绑,C++也好,或者是Smalltalk酷勺,在開(kāi)發(fā)時(shí)都會(huì)提及開(kāi)閉原則本橙。

其次,開(kāi)閉原則是最基礎(chǔ)的一個(gè)原則脆诉,前面介紹的原則都是開(kāi)閉原則的具體形態(tài)甚亭,也就是說(shuō)前五個(gè)原則就是指導(dǎo)設(shè)計(jì)的工具和方法,而開(kāi)閉原則才是其精神領(lǐng)袖库说。換一個(gè)角度理解狂鞋,依照J(rèn)ava語(yǔ)言的稱謂,開(kāi)閉原則是抽象類潜的,其他五大原則是具體的實(shí)現(xiàn)類骚揍,開(kāi)閉原則在面向?qū)ο笤O(shè)計(jì)領(lǐng)域中的地位就類似于牛頓第一定律在力學(xué)、勾股定律在幾何學(xué)啰挪、質(zhì)能方程在狹義相對(duì)論中的地位信不,其地位無(wú)人能及。

最后亡呵,開(kāi)閉原則是非常重要的抽活,可通過(guò)以下幾個(gè)方面來(lái)理解其重要性。

1锰什、開(kāi)閉原則對(duì)測(cè)試的影響

所有已經(jīng)投產(chǎn)的代碼都是有意義的下硕,并且都受系統(tǒng)規(guī)則的約束,這樣的代碼都要經(jīng)過(guò)“千錘百煉”的測(cè)試過(guò)程汁胆,不僅保證邏輯是正確的梭姓,還要保證苛刻條件(高壓力、異常嫩码、錯(cuò)誤)下不產(chǎn)生“有毒代碼(Poisonous Code)”誉尖,因此有變化提出時(shí),我們就需要考慮一下铸题,原有的健壯代碼是否可以不修改铡恕,僅僅通過(guò)擴(kuò)展實(shí)現(xiàn)變化呢?否則丢间,就需要把原有的測(cè)試過(guò)程回籠一遍探熔,需要進(jìn)行單元測(cè)試、功能測(cè)試烘挫、集成測(cè)試甚至是驗(yàn)收測(cè)試祭刚,現(xiàn)在雖然在大力提倡自動(dòng)化測(cè)試工具,但是仍然代替不了人工的測(cè)試工作。

2涡驮、 開(kāi)閉原則可以提高復(fù)用性

在面向?qū)ο蟮脑O(shè)計(jì)中,所有的邏輯都是從原子邏輯組合而來(lái)的喜滨,而不是在一個(gè)類中獨(dú)立實(shí)現(xiàn)一個(gè)業(yè)務(wù)邏輯捉捅。只有這樣代碼才可以復(fù)用,粒度越小虽风,被復(fù)用的可能性就越大。那為什么要復(fù)用呢?減少代碼量手负,避免相同的邏輯分散在多個(gè)角落飞蛹,避免日后的維護(hù)人員為了修改一個(gè)微小的缺陷或增加新功能而要在整個(gè)項(xiàng)目中到處查找相關(guān)的代碼,然后發(fā)出對(duì)開(kāi)發(fā)人員“極度失望”的感概厂抖。那怎么才能提高復(fù)用率呢茎毁?縮小邏輯粒度,直到一個(gè)邏輯不可再拆分為止忱辅。

3七蜘、開(kāi)閉原則可以提高可維護(hù)性

一款軟件投產(chǎn)后,維護(hù)人員的工作不僅僅是對(duì)數(shù)據(jù)進(jìn)行維護(hù)墙懂,還可能要對(duì)程序進(jìn)行擴(kuò)展橡卤,維護(hù)人員最樂(lè)意做的事情就是擴(kuò)展一個(gè)類,而不是修改一個(gè)類损搬,甭管原有的代碼寫得多么優(yōu)秀還是多么糟糕碧库,讓維護(hù)人員讀懂代碼原有的代碼,然后再修改巧勤,是一件很痛苦的事情嵌灰,不要讓他在原有的代碼海洋里游戈完畢后再修改,那是對(duì)維護(hù)人員的一種折磨和摧殘踢关。

4伞鲫、面向?qū)ο箝_(kāi)發(fā)的要求

萬(wàn)物皆對(duì)象,我們需要把所有的事物都抽象成對(duì)象签舞,然后針對(duì)對(duì)象進(jìn)行操作秕脓,但是萬(wàn)物皆運(yùn)動(dòng),有運(yùn)動(dòng)就有變化儒搭,有變化就要有策略去應(yīng)對(duì)吠架,怎么快速應(yīng)對(duì)呢?這就需要在設(shè)計(jì)之初考慮到所有可能變化的因素搂鲫,然后留下接口傍药,等待“可能”轉(zhuǎn)變?yōu)椤艾F(xiàn)實(shí)”。

如何使用開(kāi)閉原則

1、抽象約束

抽象是對(duì)一組事物的通用描述拐辽,沒(méi)有具體的實(shí)現(xiàn)拣挪,也就表示它可以有非常多的可能性,可以跟隨需求的變化而變化俱诸。因此菠劝,通過(guò)接口或抽象類可以約束一組可能變化的行為,并且能夠?qū)崿F(xiàn)對(duì)擴(kuò)展開(kāi)放睁搭,其包含三層含義:第一赶诊,通過(guò)接口或抽象類約束擴(kuò)展,對(duì)擴(kuò)展進(jìn)行邊界限定园骆,不允許出現(xiàn)在接口或抽象類中不存在的public方法舔痪;第二,參數(shù)類型锌唾,引用對(duì)象盡量使用接口或者抽象類锄码,而不是實(shí)現(xiàn)類;第三鸠珠,抽象層盡量保持穩(wěn)定巍耗,一旦確定即不允許修改。

2渐排、元數(shù)據(jù)(metadata)控制模塊行為

編程時(shí)使用元數(shù)據(jù)來(lái)控制程序的行為炬太,減少重復(fù)開(kāi)發(fā)。用來(lái)描述環(huán)境和數(shù)據(jù)的數(shù)據(jù)驯耻,通俗地說(shuō)就是配置參數(shù)亲族,參數(shù)可以從文件中獲得,也可以從數(shù)據(jù)中庫(kù)中獲得可缚。

3霎迫、制定項(xiàng)目章程

在一個(gè)團(tuán)隊(duì)中,建立項(xiàng)目章程是非常重要的帘靡,因?yàn)檎鲁讨兄付怂腥藛T都必須遵守的約定知给,對(duì)項(xiàng)目來(lái)說(shuō),約定優(yōu)于配置描姚。相信大家都做過(guò)項(xiàng)目涩赢,會(huì)發(fā)現(xiàn)一個(gè)項(xiàng)目會(huì)產(chǎn)生非常多的配置文件。以SSH項(xiàng)目開(kāi)發(fā)為例轩勘,一個(gè)項(xiàng)目中Bean配置文件就非常多筒扒,管理非常麻煩。如果需要擴(kuò)展绊寻,就需要增加子類花墩,并修改SpringContext文件悬秉。然而,如果你在項(xiàng)目中指定這樣一個(gè)章程:所有的Bean都自動(dòng)注入冰蘑,使用Annotation進(jìn)行裝配和泌,進(jìn)行擴(kuò)展時(shí),甚至只用寫一個(gè)類祠肥,然后由持久層生成對(duì)象允跑,其他的都不需要修改,這就需要項(xiàng)目?jī)?nèi)約束搪柑,每個(gè)項(xiàng)目成員都必須遵守,該方法需要一個(gè)團(tuán)隊(duì)有較高的自覺(jué)性索烹,需要一個(gè)較長(zhǎng)時(shí)間的磨合工碾,一旦項(xiàng)目成員都熟悉這樣的規(guī)則,比通過(guò)接口或抽象類進(jìn)行的約束效率更高百姓,而且擴(kuò)展性一點(diǎn)也沒(méi)有減少渊额。

4、封裝變化

對(duì)變化的封裝包含兩層含義:第一垒拢,將相同的變化封裝到一個(gè)接口或抽象類中旬迹;第二,將不同的變化封裝到不同的接口或抽象類中求类,不應(yīng)該有兩個(gè)不同的變化出現(xiàn)在同一個(gè)接口或抽象類中奔垦。封裝變化,也就是受保護(hù)的變化(protected variations)尸疆,找出預(yù)計(jì)有變化或不穩(wěn)定的點(diǎn)椿猎,我們?yōu)檫@些變化點(diǎn)創(chuàng)建穩(wěn)定的接口,準(zhǔn)確地講是封裝可能發(fā)生的變化寿弱,一旦預(yù)測(cè)到或“第六感”發(fā)覺(jué)有變化犯眠,就可以進(jìn)行封裝,23個(gè)設(shè)計(jì)模式都是從各個(gè)不同的角度對(duì)變化進(jìn)行封裝的症革,我們會(huì)在各個(gè)模式中逐步講解筐咧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市噪矛,隨后出現(xiàn)的幾起案子量蕊,更是在濱河造成了極大的恐慌,老刑警劉巖摩疑,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件危融,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡雷袋,警方通過(guò)查閱死者的電腦和手機(jī)吉殃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門辞居,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蛋勺,你說(shuō)我怎么就攤上這事瓦灶。” “怎么了抱完?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵贼陶,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我巧娱,道長(zhǎng)碉怔,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任禁添,我火速辦了婚禮撮胧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘老翘。我一直安慰自己芹啥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布铺峭。 她就那樣靜靜地躺著墓怀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卫键。 梳的紋絲不亂的頭發(fā)上傀履,一...
    開(kāi)封第一講書(shū)人閱讀 52,682評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音永罚,去河邊找鬼啤呼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛呢袱,可吹牛的內(nèi)容都是我干的官扣。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼羞福,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惕蹄!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起治专,我...
    開(kāi)封第一講書(shū)人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤卖陵,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后张峰,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體泪蔫,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年喘批,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了撩荣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铣揉。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖餐曹,靈堂內(nèi)的尸體忽然破棺而出逛拱,到底是詐尸還是另有隱情,我是刑警寧澤台猴,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布朽合,位于F島的核電站,受9級(jí)特大地震影響饱狂,放射性物質(zhì)發(fā)生泄漏曹步。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一休讳、第九天 我趴在偏房一處隱蔽的房頂上張望箭窜。 院中可真熱鬧,春花似錦衍腥、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至芜辕,卻和暖如春尚骄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背侵续。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工倔丈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人状蜗。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓需五,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親轧坎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宏邮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

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