日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

6大设计原则总结

發(fā)布時間:2024/4/15 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 6大设计原则总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

6大設(shè)計原則總結(jié)

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

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

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

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

  • 類的復(fù)雜性降低,實現(xiàn)什么職責(zé)都有清晰明確的定義;
  • 可讀性提高,復(fù)雜性降低,那當(dāng)然可讀性提高了;
  • 可維護性提高,可讀性提高,那當(dāng)然更容易維護了;
  • 變更引起的風(fēng)險降低,變更是必不可少的,如果接口的單一職責(zé)做得好,一個接口修改只對相應(yīng)的實現(xiàn)類有影響,對其他的接口無影響,這對系統(tǒng)的擴展性、維護性都有非常大的幫助。
  • 注意:? 單一職責(zé)原則提出了一個編寫程序的標準,用“職責(zé)”或“變化原因”來衡量接口或類設(shè)計得是否優(yōu)良,但是“職責(zé)”和“變化原因”都是不可度量的,因項目而異,因環(huán)境而異。

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

    二、里氏替換原則

    里氏替換原則(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.(如果對每一個類型為S的對象o1,都有類型為T的對象o2,使得以T定義的所有程序P在所有的對象o1都代換成o2時,程序P的行為沒有發(fā)生變化,那么類型S是類型T的子類型。)
    • 第二種定義:Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.(所有引用基類的地方必須能透明地使用其子類的對象。)

    第二個定義是最清晰明確的,通俗點講,只要父類出現(xiàn)的地方子類就可以出現(xiàn),而且替換為子類也不會產(chǎn)生任何錯誤或異常,使用者可能根本就不需要知道父類還是子類。但是反過來就不行了,有子類出現(xiàn)的地方,父類未必就能適應(yīng)。

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

  • 子類必須完全實現(xiàn)父類的方法;
  • 在類中調(diào)用其他類時務(wù)必要使用父類或接口,如果不能使用父類或接口,則說明類的設(shè)計已經(jīng)違背了LSP原則;
  • 如果子類不能完整地實現(xiàn)父類的方法,或者父類的某些方法在子類中已經(jīng)發(fā)生“畸變”,則建議斷開父子繼承關(guān)系,采用依賴、聚集、組合等關(guān)系代替繼承。
  • 子類可以有自己的個性;
  • 覆蓋或?qū)崿F(xiàn)父類的方法時輸入?yún)?shù)可以被放大;
  • 如果父類的輸入?yún)?shù)類型大于子類的輸入?yún)?shù)類型,會出現(xiàn)父類存在的地方,子類未必會存在,因為一旦把子類作為參數(shù)傳入,調(diào)用者很可能進入子類的方法范疇;
  • 子類中方法的前置條件必須與超類中被覆寫的方法的前置條件相同或者更寬松。?
  • 覆寫或?qū)崿F(xiàn)父類的方法時輸出結(jié)果可以被縮小。
  • 父類的一個方法的返回值是一個類型T,子類的相同方法(重載或覆寫)的返回值為S,那么里氏替換原則就要求S必須小于等于T,也就是說,要么S和T是同一個類型,要么S是T的子類。
  • 采用里氏替換原則的目的就是增強程序的健壯性,版本升級時也可以保持非常好的兼容性。即使增加子類,原有的子類還可以繼續(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.

    包含三層含義:

  • 高層模塊不應(yīng)該依賴底層模塊,兩者都應(yīng)該依賴抽象;
  • 抽象不應(yīng)該依賴細節(jié);
  • 細節(jié)應(yīng)該依賴抽象。
  •   高層模塊和低層模塊容易理解,每一個邏輯的實現(xiàn)都是由原子邏輯組成的,不可分割的原子邏輯就是底層模塊,原子邏輯的再組裝就是高層模塊。

    在Java語言中,抽象就是指接口或抽象類,兩者都是不能直接被實例化的;細節(jié)就是實現(xiàn)類,實現(xiàn)接口或繼承抽象類而產(chǎn)生的類就是細節(jié),其特點就是可以直接被實例化,也就是可以加上一個關(guān)鍵字new產(chǎn)生一個對象。依賴倒置原則在Java語言中的表現(xiàn)就是:

  • 模塊間的依賴通過抽象發(fā)生,實現(xiàn)類之間不發(fā)生直接的依賴關(guān)系,其依賴關(guān)系是通過接口或抽象類產(chǎn)生的;
  • 接口或抽象類不依賴于實現(xiàn)類;
  • 實現(xiàn)類依賴接口或抽象類。
  •   更加精簡的定義就是“面向接口編程”--OOD(Object-Oriented Design,面向?qū)ο笤O(shè)計)的精髓之一。

    ?依賴的三種寫法:

      依賴是可以傳遞的,A對象依賴B對象,B又依賴C,C又依賴D。。。。。。生生不息,依賴不止,記住一點:只要做到抽象依賴,即使是多層的依賴傳遞也無所畏懼!

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

  • 構(gòu)造函數(shù)傳遞依賴對象 --- 在類中通過構(gòu)造函數(shù)聲明依賴對象,按照依賴注入的說法,這種方式叫做構(gòu)造函數(shù)注入。
  • Setter方法傳遞依賴對象 --- 在抽象中設(shè)置Setter方法聲明依賴關(guān)系,依照注入的說法,這是Setter依賴注入。
  • 在接口的方法中聲明依賴對象,這種方式也叫做接口注入。
  •   依賴倒置原則的本質(zhì)就是通過抽象(接口或抽象類)使各個類或模塊的實現(xiàn)彼此獨立,不互相影響,實現(xiàn)模塊間的松耦合,我們怎么在項目中使用這個規(guī)則呢?只要遵循以下的規(guī)則就可以:

  • 每個類盡量都有接口或抽象類,或者抽象類和接口兩者都具備; --- 這是依賴倒置的基本要求,接口或抽象類都是屬于抽象的,有了抽象才可能依賴倒置。
  • 變量的表面類型盡量是接口或者是抽象類;
  • 任何類都不應(yīng)該從具體類派生;
  • 盡量不要覆寫基類的方法; --- 如果基類是一個抽象類,而且這個方法已經(jīng)實現(xiàn)了,子類盡量不要覆寫。類間依賴的是抽象,覆寫了抽象方法,對依賴的穩(wěn)定性會產(chǎn)生一定的影響。
  • 結(jié)合里氏替換原則使用。 --- 接口負責(zé)定義public屬性和方法,并且聲明與其他對象的依賴關(guān)系,抽象類負責(zé)公共構(gòu)造部分的實現(xiàn),實現(xiàn)類準確的實現(xiàn)業(yè)務(wù)邏輯,同時在適當(dāng)?shù)臅r候?qū)Ω割愡M行細化。  
  • 四、接口隔離原則

      接口分為兩種:

  • 實例接口(Object Interface),在Java中聲明一個類,然后用new關(guān)鍵字產(chǎn)生一個實例,它是對一個類型的食物的描述,這是一種接口。
  • 類接口(Class Interface),Java中經(jīng)常使用的interface關(guān)鍵字定義的接口;
  • Clients should not be forced to depend upon interfaces that they don‘t use。(客戶端不應(yīng)該依賴它不需要的接口。)
  • The dependency of one class to another one should depend on the smallest possible interface。(類間的依賴關(guān)系應(yīng)該建立在最小的接口上。)
  • 接口隔離原則是對接口進行規(guī)范約束,其包含以下4層含義:

  • 接口要盡量小; --- 這是接口隔離原則的核心定義,不出現(xiàn)臃腫的接口(Fat Interface),但是“小”是有限度的,首先就是不能違反單一職責(zé)原則。
  • 接口要高內(nèi)聚; --- 高內(nèi)聚就是提高接口、類、模塊的處理能力,減少對外的交互。在接口中盡量少公布public方法,接口是對外的承諾,承諾越少對系統(tǒng)的開發(fā)越有利,變更的風(fēng)險也就越少,同時也越有利于降低成本。
  • 定制服務(wù); --- 一個系統(tǒng)或系統(tǒng)內(nèi)的模塊之間必然會有耦合,有耦合就要有相互訪問的接口(并不一定就是Java中定義的Interface,也可能是一個類或單純的數(shù)據(jù)交換),我們設(shè)計時就需要為各個訪問者(即客戶端)定制服務(wù)。定制服務(wù)就是單獨為一個個體提供優(yōu)良的服務(wù)。我們在做系統(tǒng)設(shè)計時也需要考慮對系統(tǒng)之間或模塊之間的接口采用定制服務(wù)。采用定制服務(wù)就必然有一個要求:只提供訪問者需要的方法。
  • 接口設(shè)計是有限度的。 --- 接口的設(shè)計粒度越小,系統(tǒng)越靈活,這是不爭的事實。但是,靈活的同時也帶來了結(jié)構(gòu)的復(fù)雜化,開發(fā)難度增加,可維護性低,這不是一個項目或產(chǎn)品所期望看到的,所以接口設(shè)計一定要注意適度,這個“度”如何來判斷?根據(jù)經(jīng)驗和常識判斷,沒有一個固話或可測量的標準。
  •   接口隔離原則是對接口的定義,同時也是對類的定義,接口和類盡量使用原子接口或原子類來組裝。但是,這個原子該怎么劃分是設(shè)計模式中的一大難題,在實踐中可以根據(jù)以下幾個規(guī)則來衡量:

  • 一個接口只服務(wù)于一個模塊或業(yè)務(wù)邏輯;
  • 通過業(yè)務(wù)邏輯壓縮接口中的public方法,接口時常去回顧,盡量讓接口達到“滿身筋骨肉”,而不是“肥嘟嘟”的一大堆方法;
  • 已經(jīng)被污染了的接口,盡量去修改,若變更的風(fēng)險較大,則采用適配器模式進行轉(zhuǎn)化處理;
  • 了解環(huán)境,拒絕盲從。每個項目或產(chǎn)品都有特定的環(huán)境因素,別看到大師是這樣做的你就照抄。千萬別,環(huán)境不同,接口拆分的標準就不同。深入了解業(yè)務(wù)邏輯,最好的接口設(shè)計就出自你的手中!
  • 五、迪米特法則

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

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

  • 只和朋友交流 --- 迪米特法則還有一個英文解釋是:Only talk to your immedate friends(只與直接的朋友通信。)什么叫做直接的朋友?每個對象都必然會與其他對象有耦合關(guān)系,兩個對象之間的耦合就成為朋友關(guān)系,這種關(guān)系的類型有很多,例如組合、聚合、依賴等。朋友類的定義:出現(xiàn)在成員變量、方法的輸入輸出參數(shù)中的類稱為成員朋友類,而出現(xiàn)在方法體內(nèi)部的類不屬于朋友類。注意:一個類只和朋友交流,不與陌生類交流,不要出現(xiàn)getA().getB().getC().getD()這種情況(在一種極端的情況下允許出現(xiàn)這種訪問,即每一個點后面返回類型都相同),類與類之間的關(guān)系是建立在類間的,而不是方法間,因此一個方法盡量不引入一個類中不存在的對象,當(dāng)然,JDK API提供的類除外。
  • 朋友間也是有距離的 --- 一個類公開的public屬性或方法越多,修改時涉及的面積越大,變更引起的風(fēng)險擴散也就越大。因此,為了保持朋友類間的距離,在設(shè)計時需要反復(fù)衡量:是否還可以再減少public方法和屬性,是否可以修改為private、package-private(包類型,在類、方法、變量前不加訪問權(quán)限,則默認為包類型)、protected 等訪問權(quán)限,是否可以加上final關(guān)鍵字等。? 注意:迪米特法則要求類“羞澀”一點,盡量不要對外公布太多的public方法和非靜態(tài)的public變量,盡量內(nèi)斂,多使用private、package-private、protected等訪問權(quán)限。
  • 是自己的就是自己的 --- 如果一個方法放在本類中,即不增加類間的關(guān)系,也對本類不產(chǎn)生負面影響,就放置在本類中。
  • 謹慎使用Serializable
  •   迪米特法則的核心觀念就是類間解耦,弱耦合,只有弱耦合了以后,類的復(fù)用率才可以提高。其要求的結(jié)果就是產(chǎn)生了大量的中轉(zhuǎn)或跳轉(zhuǎn)類,導(dǎo)致系統(tǒng)的復(fù)雜性提高,同時也為維護帶來了難度。

      迪米特法則要求類間解耦,但解耦是有限度的,除非是計算機的最小單元——二進制的0和1。那才是完全解耦,在實際的項目中,需要適度地考慮這個原則,別為了套用原則而做項目。原則只是供參考,如果違背了這個原則,項目也未必會失敗,這就需要大家在采用原則時反復(fù)度量,不遵循是不對的,嚴格執(zhí)行就是“過猶不及”。

    六、開放封閉原則

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

  • 項目或軟件產(chǎn)品中按照一定的邏輯規(guī)則劃分的模塊;
  • 抽象和類;
  • 方法。
  •   一個軟件產(chǎn)品只要在生命周期內(nèi),都會發(fā)生變化,既然變化是一個既定的事實,我們就應(yīng)該在設(shè)計時盡量適應(yīng)這些變化,以提高項目的穩(wěn)定性和靈活性,真正實現(xiàn)“擁抱變化”。開放封閉原則告訴我們應(yīng)盡量通過擴展軟件實體的行為來實現(xiàn)變化,而不是通過修改已有的代碼來完成變化,它是為軟件實體的未來事件而制定的對現(xiàn)行開發(fā)設(shè)計進行約束的一個原則。

      開放封閉原則對擴展開放,對修改封閉,并不意味著不做任何修改,低層模塊的變更,必然要有高層模塊進行耦合,否則就是一個孤立無意義的代碼片段。我們可以把變化歸納以下三種類型:

  • 邏輯變化; -- 只變化一個邏輯,而不涉及其他模塊,比如原有的一個算法是 a*b+c ,現(xiàn)在需要修改為 a*b*c ,可以通過修改原有類中的方法的方式來完成,前提條件是所有依賴關(guān)系都按照相同的邏輯處理。
  • 子模塊變化; ---一個模塊變化,會對其他的模塊產(chǎn)生影響,特別是一個低層次的模塊變化必然引起高層次模塊的變化,因此在通過擴展完成變化時,高層次的模塊修改是必然的。
  • 可見視圖變化 --- 可見視圖是提供給客戶使用的界面,如JSP程序、Swing界面等,該部分的變化一般會引起連鎖反應(yīng)(特別是在國內(nèi)做項目,做歐美的外包項目一般不會影響太大)。如果僅僅是界面上按鈕、文字的重新排列倒是簡單,最司空見慣的是業(yè)務(wù)耦合變化,什么意思?一個展示數(shù)據(jù)的列表,按照原有的需求是6列,突然有一天要增加1列,而且這一列要跨N張表,處理M個邏輯才能展現(xiàn)出來,這樣的變化是比較恐怖的,但還是可以通過擴展來完成變化,這就要看我們原有的設(shè)計是否靈活。
  • 為什么要采用開放封閉原則:

      每個事物的誕生都有它存在的必要性,存在即合理,那開閉原則的存在也是合理的,為什么這么說呢?

      首先,開閉原則是那么地著名,只要是做面向?qū)ο缶幊痰?#xff0c;甭管是什么語言,Java也好,C++也好,或者是Smalltalk,在開發(fā)時都會提及開閉原則。

      其次,開閉原則是最基礎(chǔ)的一個原則,前面介紹的原則都是開閉原則的具體形態(tài),也就是說前五個原則就是指導(dǎo)設(shè)計的工具和方法,而開閉原則才是其精神領(lǐng)袖。換一個角度理解,依照Java語言的稱謂,開閉原則是抽象類,其他五大原則是具體的實現(xiàn)類,開閉原則在面向?qū)ο笤O(shè)計領(lǐng)域中的地位就類似于牛頓第一定律在力學(xué)、勾股定律在幾何學(xué)、質(zhì)能方程在狹義相對論中的地位,其地位無人能及。

      最后,開閉原則是非常重要的,可通過以下幾個方面來理解其重要性。

      1、開閉原則對測試的影響

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

      2、?開閉原則可以提高復(fù)用性

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

      3、開閉原則可以提高可維護性

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

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

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

    如何使用開閉原則

      1、抽象約束

      抽象是對一組事物的通用描述,沒有具體的實現(xiàn),也就表示它可以有非常多的可能性,可以跟隨需求的變化而變化。因此,通過接口或抽象類可以約束一組可能變化的行為,并且能夠?qū)崿F(xiàn)對擴展開放,其包含三層含義:第一,通過接口或抽象類約束擴展,對擴展進行邊界限定,不允許出現(xiàn)在接口或抽象類中不存在的public方法;第二,參數(shù)類型,引用對象盡量使用接口或者抽象類,而不是實現(xiàn)類;第三,抽象層盡量保持穩(wěn)定,一旦確定即不允許修改。

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

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

      3、制定項目章程

      在一個團隊中,建立項目章程是非常重要的,因為章程中指定了所有人員都必須遵守的約定,對項目來說,約定優(yōu)于配置。相信大家都做過項目,會發(fā)現(xiàn)一個項目會產(chǎn)生非常多的配置文件。以SSH項目開發(fā)為例,一個項目中Bean配置文件就非常多,管理非常麻煩。如果需要擴展,就需要增加子類,并修改SpringContext文件。然而,如果你在項目中指定這樣一個章程:所有的Bean都自動注入,使用Annotation進行裝配,進行擴展時,甚至只用寫一個類,然后由持久層生成對象,其他的都不需要修改,這就需要項目內(nèi)約束,每個項目成員都必須遵守,該方法需要一個團隊有較高的自覺性,需要一個較長時間的磨合,一旦項目成員都熟悉這樣的規(guī)則,比通過接口或抽象類進行的約束效率更高,而且擴展性一點也沒有減少。

      4、封裝變化

      對變化的封裝包含兩層含義:第一,將相同的變化封裝到一個接口或抽象類中;第二,將不同的變化封裝到不同的接口或抽象類中,不應(yīng)該有兩個不同的變化出現(xiàn)在同一個接口或抽象類中。封裝變化,也就是受保護的變化(protected variations),找出預(yù)計有變化或不穩(wěn)定的點,我們?yōu)檫@些變化點創(chuàng)建穩(wěn)定的接口,準確地講是封裝可能發(fā)生的變化,一旦預(yù)測到或“第六感”發(fā)覺有變化,就可以進行封裝,23個設(shè)計模式都是從各個不同的角度對變化進行封裝的,我們會在各個模式中逐步講解。

    ?

    ?

    ?

    https://cloud.tencent.com/developer/support-plan?invite_code=2a5lqtvqtu3o8

    轉(zhuǎn)載于:https://www.cnblogs.com/DI-DIAO/p/8613357.html

    總結(jié)

    以上是生活随笔為你收集整理的6大设计原则总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。