設計模式6大原則:里氏置換原則

1. 里氏替換原則

裏式替換原則(Liskov Substitution Principle,LSP),全部引用基類的地方必須可以透明的使用其子類對象。也就是說,只要父類出現的地方都能替換爲子類,不會產生異常。可是反過來,子類出現的地方,替換爲父類就可能出現問題。 也就是子類能夠擴展父類的功能,但不能改變父類的功能。 通俗的講:類須要擴展功能時,新類繼承舊類,使用新類替換舊類不會形成故障。 
1. 子類能夠實現父類的抽象方法,但不能覆蓋父類的非抽象方法; 
2. 子類中能夠增長本身持有的方法; 
3. 當子類的方法重載父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬鬆; 
4. 當子類的方法實現父類的抽象方法是,方法的後置條件(即方法的返回值)要比父類更嚴格。html

2. 單一職責原則

單一職責原則(Single Responsibility Principle, SRP), 
There should never be more than one reason for a class to change. (應該有且僅有一個緣由引發類的變動) 
如下摘自:http://blog.csdn.net/vebasan/article/details/8003102 
有時候,開發人員設計接口的時候,將用戶的屬性和用戶的行爲放在一個接口中聲明。這就形成業務對象和業務邏輯放在一塊兒了。 
例子:web

public interface Itutu {
    //height
    void setHeight(double height);    void getHeight();    //weight
    void setWeight(double weight);    void getWeight();    //eat
    void eat(boolean hungry);    //surf in internet
    void internet(boolean buy);
}

單一職責的意義 
1. 下降類的複雜性,實現什麼樣的職責都有清晰的定義; 
2. 提升可讀性和可維護性; 
3. 下降變動引發的風險,對系統擴展性和維護性頗有幫助。編程

3. 依賴倒置原則

依賴倒置原則(Dependency Inversion Principle, DIP) 
Definition: 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.框架

即:高層模塊不該該依賴低層模塊,兩者都應該依賴其抽象。抽象不該該依賴細節,細節應該依賴抽象。工具

抽象:即抽象類或接口,是不可以實例化的。this

細節:即具體的實現類,實現接口或者繼承抽象類所產生的類,能夠經過關鍵字new直接被實例化。spa

每個邏輯的實現都是由原子邏輯組成的,不可分割的原子邏輯就是低層模塊,原子邏輯的再組裝就是高層模塊。.net

面向接口編程 
如下摘自http://www.cnblogs.com/cbf4life/archive/2009/12/15/1624435.html設計

講了這麼多,估計你們對「倒置」這個詞仍是有點不理解,那到底什麼是「倒置」呢?咱們先說「正置」是什麼意思,依賴正置就是類間的依賴是實實在在的實現類間的依賴,也就是面向實現編程,這也是正常人的思惟方式,我要開奔馳車就依賴奔馳車,我要使用筆記本電腦就直接依賴筆記本電腦,而編寫程序須要的是對現實世界的事物進行抽象,抽象的結果就是有了抽象類和接口,而後咱們根據系統設計的須要產生了抽象間的依賴,代替了人們傳統思惟中的事物間的依賴,「倒置」就是從這裏產生的。code

依賴倒轉原則的本質就是經過抽象(接口或抽象類)使各個類或模塊的實現彼此獨立,不互相影響,實現模塊間的鬆耦合,咱們怎麼在項目中使用這個規則呢?只要遵循如下的幾個規則就能夠:

每一個類儘可能都有接口或抽象類,或者抽象類和接口二者都具有。 
這是依賴倒置的基本要求,接口和抽象類都是屬於抽象的,有了抽象纔可能依賴倒置。

變量的顯示類型儘可能是接口或者是抽象類。 
不少書上說變量的類型必定要是接口或者是抽象類,這個有點絕對化了,好比一個工具類,xxxUtils通常是不須要接口或是抽象類的。還有,若是你要使用類的clone方法,就必須使用實現類,這個是JDK提供一個規範。

任何類都不該該從具體類派生。 
若是一個項目處於開發狀態,確實不該該有從具體類派生出的子類的狀況,但這也不是絕對的,由於人都是會犯錯誤的,有時設計缺陷是在所不免的,所以只要不超過兩層的繼承都是能夠忍受的。特別是作項目維護的同志,基本上能夠不考慮這個規則,爲何?維護工做基本上都是作擴展開發,修復行爲,經過一個繼承關係,覆寫一個方法就能夠修正一個很大的Bug,何須再要去繼承最高的基類呢?

儘可能不要覆寫基類的方法。 
若是基類是一個抽象類,並且這個方法已經實現了,子類儘可能不要覆寫。類間依賴的是抽象,覆寫了抽象方法,對依賴的穩定性會產生必定的影響。

4. 開閉原則

抽象層肯定後再也不修改。經過抽象層導出多個新的具體類實現擴展。

5. 接口隔離原則

客戶端不該該不依賴它不須要的接口,一個類對另外一個類的依賴應該創建在最小的接口上。使用多個專門的接口比使用單一的總接口要好。 
一個類對另一個類的依賴性應當是創建在最小的接口上的。 
一個接口表明一個角色,不該當將不一樣的角色都交給一個接口。沒有關係的接口合併在一塊兒,造成一個臃腫的大接口,這是對角色和接口的污染。 
「不該該強迫客戶依賴於它們不用的方法。接口屬於客戶,不屬於它所在的類層次結構。」這個說得很明白了,再通俗點說,不要強迫客戶使用它們不用的方法,若是強迫用戶使用它們不使用的方法,那麼這些客戶就會面臨因爲這些不使用的方法的改變所帶來的改變。

接口隔離原則的含義是:創建單一接口,不要創建龐大臃腫的接口,儘可能細化接口,接口中的方法儘可能少。也就是說,咱們要爲各個類創建專用的接口,而不要試圖去創建一個很龐大的接口供全部依賴它的類去調用。本文例子中,將一個龐大的接口變動爲3個專用的接口所採用的就是接口隔離原則。在程序設計中,依賴幾個專用的接口要比依賴一個綜合的接口更靈活。接口是設計時對外部設定的「契約」,經過分散定義多個接口,能夠預防外來變動的擴散,提升系統的靈活性和可維護性。

說到這裏,不少人會覺的接口隔離原則跟以前的單一職責原則很類似,其實否則。其一,單一職責原則原注重的是職責;而接口隔離原則注重對接口依賴的隔離。其二,單一職責原則主要是約束類,其次纔是接口和方法,它針對的是程序中的實現和細節;而接口隔離原則主要約束接口接口,主要針對抽象,針對程序總體框架的構建。

採用接口隔離原則對接口進行約束時,要注意如下幾點:

接口儘可能小,可是要有限度。對接口進行細化能夠提升程序設計靈活性是不掙的事實,可是若是太小,則會形成接口數量過多,使設計複雜化。因此必定要適度。 
爲依賴接口的類定製服務,只暴露給調用的類它須要的方法,它不須要的方法則隱藏起來。只有專一地爲一個模塊提供定製服務,才能創建最小的依賴關係。 
提升內聚,減小對外交互。使接口用最少的方法去完成最多的事情。 
運用接口隔離原則,必定要適度,接口設計的過大或太小都很差。設計接口的時候,只有多花些時間去思考和籌劃,才能準確地實踐這一原則。

6. 迪米特法則

也稱爲最少知識原則(LeastKnowledge Principle, LKP): 一個軟件實體應當儘量少的與其餘實體發生相互做用。當一個模塊發生修改時,儘可能少地影響其餘模塊。

迪米特法則還有幾種定義形式,包括:不要和「陌生人」說話、只與你的直接朋友通訊等,在迪米特法則中,對於一個對象,其朋友包括如下幾類:(1) 當前對象自己(this);(2) 以參數形式傳入到當前對象方法中的對象;(3) 當前對象的成員對象;(4) 若是當前對象的成員對象是一個集合,那麼集合中的元素也都是朋友;(5) 當前對象所建立的對象。

相關文章
相關標籤/搜索