設計原則解讀——單一職責原則、里氏替換原則

單一替換原則

定義:There should never be more than one reasion for a change.編程

應該有且僅有一個緣由引發類的變動(類的職責應該儘量的單一)。設計模式

若是一個類有一個以上的職責,這些職責就耦合在了一塊兒。這會致使脆弱的設計。當一個職責發生變化時,可能會影響其它的職責。另外,多個職責耦合在一塊兒,會影響複用性。安全


例如:編碼

對於一個用戶管理類,應該把用戶信息抽取成BO(接口),把行爲抽取成Biz(接口),最後繼承這兩個接口。spa

反思在以前不少的編碼當中,單一職責考慮的不夠,需求或其餘模塊的變化最終致使代碼大規模的修改。設計


面向接口編程與單一職責:對象

一個接口或類只有一個緣由引發變化,也就是一個接口或類只有一個職責。繼承

單一職責應該考慮面向接口編程,每一個接口職責分明,而後把多個職責融合在一個類中。而不是採用組合模式,由於組合自己是一種強耦合關係。接口

單一職責能給咱們在編程中帶來以下好處:io

  1. 下降類的複雜度,提升可讀性,提升可讀性;

  2. 變動引發的風險下降,對系統擴展性,維護性都有很大幫助

最後:單一職責不只適用於接口和類,同時適用於方法,一個方法應該儘量作一件事情,避免一個方法的顆粒度粗。

在實際項目中可能常常違背單一職責,接口必定要作到單一職責,類的設計儘可能作到一個緣由引發變化。


里氏替換原則(LSP原則)

通俗理解:只要父類出現的地方子類就能夠出現,替換不會產生任何錯誤和異常。

「繼承必須確保超類所擁有的性質在子類中仍然成立。」也就是說,當一個子類的實例應該可以替換任何其超類的實例時,它們之間才具備is-A關係。

里氏替換原則隱含的四層含義:

  1. 子類必須徹底實現父類的方法

  2. 子類能夠有本身的「個性」

  3. 覆蓋或實現父類的方法時輸入參數能夠被放大

  4. 覆蓋或實現父類的方法時輸出結果可能被縮小

對以上四層的說明:

1. 是否繼承?

實際設計中若是子類不能完整地實現父類的方法,或者父類的某些方法在子類中已經發生「畸變」,應該斷開繼承關係,採用依賴,彙集,組合等關係代替繼承(實際編碼中繼承應該謹慎被使用,繼承是侵入式的,增長了子類的約束,加強了類之間的耦合性)。在類中調用其餘類時務必要使用父類或接口,若是不能使用父類或藉口,則說明類的設計已經違背了LSP原則。

2.里氏替換原則逆用? 

在子類出現的地方,父類未必就可以勝任。也就是常說的向下轉型(downcast)是不安全的(里氏替換原則反過來未必成立)。

3.前置條件、後置條件、不變式

前置條件:每一個方法調用以前,該方法應該校驗傳入參數的正確性,只有正確才能執行該方法,不然認爲調用方違反契約,應不予執行。

後置條件:一旦經過前置條件的校驗,方法必須執行,而且必須確保執行結果符合契約。

不變式:對象自己有一套對自身狀態進行校驗的檢查條件,以確保該對象的本質不發生改變。

4.輸入、輸出與LBS

了知足LSP,當存在繼承關係時,子類中方法的前置條件必須與超類中被覆蓋的方法的前置條件相同或者更寬鬆(避免業務邏輯的混亂);

而子類中方法的後置條件必須與超類中被覆蓋的方法的後置條件相同或者更爲嚴格。

繼承而且覆蓋超類方法的時候,子類中的方法的可見性必須等於或者大於超類中的方法的可見性,子類中的方法所拋出的受檢異常只能是超類中對應方法所拋出的受檢異常的子類。

5.里氏替換原則的目的

採用里氏替換原則的目的就是爲了加強程序的健壯性,可擴展性。

6.子類的「個性」。

當一個子類很個性時,這個子類就和父類的關係很難調和,把子類當作父類使用會使子類失掉「個性」。

可是若獨立做爲一個業務使用,又會使代碼間耦合關係不清晰。


參考資料:

《設計模式之禪》        機械工業出版社            秦小波著

百度百科——單一職責原則、里氏替換原則

來自互聯網其它資料

相關文章
相關標籤/搜索