6大设计原则总结
6大設計原則總結
一、單一職責原則
?單一職責原則:英文名稱是Single Responsiblity Principle,簡稱是SRP。定義:應該有且僅有一個原因引起類的變更。
單一職責原則要求:一個接口或類只有一個原因引起變化,也就是一個接口或類只有一個職責,它就負責一件事情。
單一職責原則的好處:
注意:? 單一職責原則提出了一個編寫程序的標準,用“職責”或“變化原因”來衡量接口或類設計得是否優良,但是“職責”和“變化原因”都是不可度量的,因項目而異,因環境而異。
對于單一職責原則,接口一定要做到單一職責,類的設計盡量做到只有一個原因引起變化。
二、里氏替換原則
里氏替換原則(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的行為沒有發生變化,那么類型S是類型T的子類型。)
- 第二種定義:Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.(所有引用基類的地方必須能透明地使用其子類的對象。)
第二個定義是最清晰明確的,通俗點講,只要父類出現的地方子類就可以出現,而且替換為子類也不會產生任何錯誤或異常,使用者可能根本就不需要知道父類還是子類。但是反過來就不行了,有子類出現的地方,父類未必就能適應。
里氏替換原則為良好的繼承定義了一個規范,一句簡單的定義包含了4層含義:
采用里氏替換原則的目的就是增強程序的健壯性,版本升級時也可以保持非常好的兼容性。即使增加子類,原有的子類還可以繼續執行。
三、依賴倒置原則
依賴倒置原則(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.
包含三層含義:
高層模塊和低層模塊容易理解,每一個邏輯的實現都是由原子邏輯組成的,不可分割的原子邏輯就是底層模塊,原子邏輯的再組裝就是高層模塊。
在Java語言中,抽象就是指接口或抽象類,兩者都是不能直接被實例化的;細節就是實現類,實現接口或繼承抽象類而產生的類就是細節,其特點就是可以直接被實例化,也就是可以加上一個關鍵字new產生一個對象。依賴倒置原則在Java語言中的表現就是:
更加精簡的定義就是“面向接口編程”--OOD(Object-Oriented Design,面向對象設計)的精髓之一。
?依賴的三種寫法:
依賴是可以傳遞的,A對象依賴B對象,B又依賴C,C又依賴D。。。。。。生生不息,依賴不止,記住一點:只要做到抽象依賴,即使是多層的依賴傳遞也無所畏懼!
對象的依賴關系有三種方式來傳遞:
依賴倒置原則的本質就是通過抽象(接口或抽象類)使各個類或模塊的實現彼此獨立,不互相影響,實現模塊間的松耦合,我們怎么在項目中使用這個規則呢?只要遵循以下的規則就可以:
四、接口隔離原則
接口分為兩種:
接口隔離原則是對接口進行規范約束,其包含以下4層含義:
接口隔離原則是對接口的定義,同時也是對類的定義,接口和類盡量使用原子接口或原子類來組裝。但是,這個原子該怎么劃分是設計模式中的一大難題,在實踐中可以根據以下幾個規則來衡量:
五、迪米特法則
迪米特法則(Law of Demeter ,LoD)也稱為最少知識原則(Least Knowledge Principle,LKP),雖然名字不同,但描述的是同一個規則:一個對象應該對其他對象有最少的了解。通俗地講,一個類應該對自己需要耦合或調用的類知道得最少,你(被耦合或調用的類)的內部是如何復雜都和我沒關系,那是你的事情,我就知道你提供的這么多public方法,我就調用這么多,其他的我一概不關心。
迪米特法則對類的低耦合提出了明確的要求,其包含以下4層含義:
迪米特法則的核心觀念就是類間解耦,弱耦合,只有弱耦合了以后,類的復用率才可以提高。其要求的結果就是產生了大量的中轉或跳轉類,導致系統的復雜性提高,同時也為維護帶來了難度。
迪米特法則要求類間解耦,但解耦是有限度的,除非是計算機的最小單元——二進制的0和1。那才是完全解耦,在實際的項目中,需要適度地考慮這個原則,別為了套用原則而做項目。原則只是供參考,如果違背了這個原則,項目也未必會失敗,這就需要大家在采用原則時反復度量,不遵循是不對的,嚴格執行就是“過猶不及”。
六、開放封閉原則
開放封閉原則的定義:Software entities like classes, modules and functions should be open for extension but closed for modifications.(一個軟件實體如類、模塊和函數應該對擴展開放,對修改關閉。)其含義是說一個軟件實體應該通過擴展來實現變化。軟實體包括以下幾個部分:
一個軟件產品只要在生命周期內,都會發生變化,既然變化是一個既定的事實,我們就應該在設計時盡量適應這些變化,以提高項目的穩定性和靈活性,真正實現“擁抱變化”。開放封閉原則告訴我們應盡量通過擴展軟件實體的行為來實現變化,而不是通過修改已有的代碼來完成變化,它是為軟件實體的未來事件而制定的對現行開發設計進行約束的一個原則。
開放封閉原則對擴展開放,對修改封閉,并不意味著不做任何修改,低層模塊的變更,必然要有高層模塊進行耦合,否則就是一個孤立無意義的代碼片段。我們可以把變化歸納以下三種類型:
為什么要采用開放封閉原則:
每個事物的誕生都有它存在的必要性,存在即合理,那開閉原則的存在也是合理的,為什么這么說呢?
首先,開閉原則是那么地著名,只要是做面向對象編程的,甭管是什么語言,Java也好,C++也好,或者是Smalltalk,在開發時都會提及開閉原則。
其次,開閉原則是最基礎的一個原則,前面介紹的原則都是開閉原則的具體形態,也就是說前五個原則就是指導設計的工具和方法,而開閉原則才是其精神領袖。換一個角度理解,依照Java語言的稱謂,開閉原則是抽象類,其他五大原則是具體的實現類,開閉原則在面向對象設計領域中的地位就類似于牛頓第一定律在力學、勾股定律在幾何學、質能方程在狹義相對論中的地位,其地位無人能及。
最后,開閉原則是非常重要的,可通過以下幾個方面來理解其重要性。
1、開閉原則對測試的影響
所有已經投產的代碼都是有意義的,并且都受系統規則的約束,這樣的代碼都要經過“千錘百煉”的測試過程,不僅保證邏輯是正確的,還要保證苛刻條件(高壓力、異常、錯誤)下不產生“有毒代碼(Poisonous Code)”,因此有變化提出時,我們就需要考慮一下,原有的健壯代碼是否可以不修改,僅僅通過擴展實現變化呢?否則,就需要把原有的測試過程回籠一遍,需要進行單元測試、功能測試、集成測試甚至是驗收測試,現在雖然在大力提倡自動化測試工具,但是仍然代替不了人工的測試工作。
2、?開閉原則可以提高復用性
在面向對象的設計中,所有的邏輯都是從原子邏輯組合而來的,而不是在一個類中獨立實現一個業務邏輯。只有這樣代碼才可以復用,粒度越小,被復用的可能性就越大。那為什么要復用呢?減少代碼量,避免相同的邏輯分散在多個角落,避免日后的維護人員為了修改一個微小的缺陷或增加新功能而要在整個項目中到處查找相關的代碼,然后發出對開發人員“極度失望”的感概。那怎么才能提高復用率呢?縮小邏輯粒度,直到一個邏輯不可再拆分為止。
3、開閉原則可以提高可維護性
一款軟件投產后,維護人員的工作不僅僅是對數據進行維護,還可能要對程序進行擴展,維護人員最樂意做的事情就是擴展一個類,而不是修改一個類,甭管原有的代碼寫得多么優秀還是多么糟糕,讓維護人員讀懂代碼原有的代碼,然后再修改,是一件很痛苦的事情,不要讓他在原有的代碼海洋里游戈完畢后再修改,那是對維護人員的一種折磨和摧殘。
4、面向對象開發的要求
萬物皆對象,我們需要把所有的事物都抽象成對象,然后針對對象進行操作,但是萬物皆運動,有運動就有變化,有變化就要有策略去應對,怎么快速應對呢?這就需要在設計之初考慮到所有可能變化的因素,然后留下接口,等待“可能”轉變為“現實”。
如何使用開閉原則
1、抽象約束
抽象是對一組事物的通用描述,沒有具體的實現,也就表示它可以有非常多的可能性,可以跟隨需求的變化而變化。因此,通過接口或抽象類可以約束一組可能變化的行為,并且能夠實現對擴展開放,其包含三層含義:第一,通過接口或抽象類約束擴展,對擴展進行邊界限定,不允許出現在接口或抽象類中不存在的public方法;第二,參數類型,引用對象盡量使用接口或者抽象類,而不是實現類;第三,抽象層盡量保持穩定,一旦確定即不允許修改。
2、元數據(metadata)控制模塊行為
編程時使用元數據來控制程序的行為,減少重復開發。用來描述環境和數據的數據,通俗地說就是配置參數,參數可以從文件中獲得,也可以從數據中庫中獲得。
3、制定項目章程
在一個團隊中,建立項目章程是非常重要的,因為章程中指定了所有人員都必須遵守的約定,對項目來說,約定優于配置。相信大家都做過項目,會發現一個項目會產生非常多的配置文件。以SSH項目開發為例,一個項目中Bean配置文件就非常多,管理非常麻煩。如果需要擴展,就需要增加子類,并修改SpringContext文件。然而,如果你在項目中指定這樣一個章程:所有的Bean都自動注入,使用Annotation進行裝配,進行擴展時,甚至只用寫一個類,然后由持久層生成對象,其他的都不需要修改,這就需要項目內約束,每個項目成員都必須遵守,該方法需要一個團隊有較高的自覺性,需要一個較長時間的磨合,一旦項目成員都熟悉這樣的規則,比通過接口或抽象類進行的約束效率更高,而且擴展性一點也沒有減少。
4、封裝變化
對變化的封裝包含兩層含義:第一,將相同的變化封裝到一個接口或抽象類中;第二,將不同的變化封裝到不同的接口或抽象類中,不應該有兩個不同的變化出現在同一個接口或抽象類中。封裝變化,也就是受保護的變化(protected variations),找出預計有變化或不穩定的點,我們為這些變化點創建穩定的接口,準確地講是封裝可能發生的變化,一旦預測到或“第六感”發覺有變化,就可以進行封裝,23個設計模式都是從各個不同的角度對變化進行封裝的,我們會在各個模式中逐步講解。
?
?
?
https://cloud.tencent.com/developer/support-plan?invite_code=2a5lqtvqtu3o8
轉載于:https://www.cnblogs.com/DI-DIAO/p/8613357.html
總結
- 上一篇: bzoj1407: [Noi2002]S
- 下一篇: RANSAC与 最小二乘(LS, Lea