6大设计原则总结
6大設(shè)計原則總結(jié)
一、單一職責(zé)原則
?單一職責(zé)原則:英文名稱是Single Responsiblity Principle,簡稱是SRP。定義:應(yīng)該有且僅有一個原因引起類的變更。
單一職責(zé)原則要求:一個接口或類只有一個原因引起變化,也就是一個接口或類只有一個職責(zé),它就負責(zé)一件事情。
單一職責(zé)原則的好處:
注意:? 單一職責(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層含義:
采用里氏替換原則的目的就是增強程序的健壯性,版本升級時也可以保持非常好的兼容性。即使增加子類,原有的子類還可以繼續(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.
包含三層含義:
高層模塊和低層模塊容易理解,每一個邏輯的實現(xiàn)都是由原子邏輯組成的,不可分割的原子邏輯就是底層模塊,原子邏輯的再組裝就是高層模塊。
在Java語言中,抽象就是指接口或抽象類,兩者都是不能直接被實例化的;細節(jié)就是實現(xiàn)類,實現(xiàn)接口或繼承抽象類而產(chǎn)生的類就是細節(jié),其特點就是可以直接被實例化,也就是可以加上一個關(guān)鍵字new產(chǎn)生一個對象。依賴倒置原則在Java語言中的表現(xiàn)就是:
更加精簡的定義就是“面向接口編程”--OOD(Object-Oriented Design,面向?qū)ο笤O(shè)計)的精髓之一。
?依賴的三種寫法:
依賴是可以傳遞的,A對象依賴B對象,B又依賴C,C又依賴D。。。。。。生生不息,依賴不止,記住一點:只要做到抽象依賴,即使是多層的依賴傳遞也無所畏懼!
對象的依賴關(guān)系有三種方式來傳遞:
依賴倒置原則的本質(zhì)就是通過抽象(接口或抽象類)使各個類或模塊的實現(xiàn)彼此獨立,不互相影響,實現(xiàn)模塊間的松耦合,我們怎么在項目中使用這個規(guī)則呢?只要遵循以下的規(guī)則就可以:
四、接口隔離原則
接口分為兩種:
接口隔離原則是對接口進行規(guī)范約束,其包含以下4層含義:
接口隔離原則是對接口的定義,同時也是對類的定義,接口和類盡量使用原子接口或原子類來組裝。但是,這個原子該怎么劃分是設(shè)計模式中的一大難題,在實踐中可以根據(jù)以下幾個規(guī)則來衡量:
五、迪米特法則
迪米特法則(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層含義:
迪米特法則的核心觀念就是類間解耦,弱耦合,只有弱耦合了以后,類的復(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)品只要在生命周期內(nèi),都會發(fā)生變化,既然變化是一個既定的事實,我們就應(yīng)該在設(shè)計時盡量適應(yīng)這些變化,以提高項目的穩(wěn)定性和靈活性,真正實現(xiàn)“擁抱變化”。開放封閉原則告訴我們應(yīng)盡量通過擴展軟件實體的行為來實現(xiàn)變化,而不是通過修改已有的代碼來完成變化,它是為軟件實體的未來事件而制定的對現(xiàn)行開發(fā)設(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é)
- 上一篇: bzoj1407: [Noi2002]S
- 下一篇: RANSAC与 最小二乘(LS, Lea