1. 程式人生 > 其它 >《設計模式之禪》讀書筆記(一)

《設計模式之禪》讀書筆記(一)

六大設計原則

單一職責原則

定義:應該有且僅有一個原因引起類的變更。

舉例:屬性和行為拆分,例如 setPassword(String password) 和 changePassword(String password)。

單一職責原則提出了一個編寫程式的標準,用“職責”或“變化原因”來衡量介面或類設計得是否優良,但是“職責”和“變化原因”都是不可度量的,因專案而異,因環境而異。 對於單一職責原則,建議是介面一定要做到單一職責,類的設計儘量做到只有一個原因引起變化。

里氏替換原則

定義:所有引用基類的地方必須能透明地使用其子類的物件。

1.子類必須完全實現父類的方法。

2.子類可以有自己的個性。

3.覆蓋或實現父類的方法時輸入引數可以被放大。(這裡要注意覆寫(Override)和過載(Overload)的區別,子類中方法的前置條件必須與超類中被覆寫的方法的前置條件相同或者更寬鬆。)

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

在類中呼叫其他類時務必要使用父類或介面,如果不能使用父類或介面,則說明類的設計已經違背了LSP原則。如果子類不能完整地實現父類的方法,或者父類的某些方法在子類中已經發生“畸變”,則建議斷開父子繼承關係,採用依賴、聚集、組合等關係代替繼承。

依賴倒置原則

定義:高層模組不應該依賴低層模組,兩者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。

依賴的三種傳遞方式:建構函式傳遞依賴物件;Setter方法傳遞依賴物件;介面宣告依賴物件。

依賴倒置原則的本質就是通過抽象(介面或抽象類)使各個類或模組的實現彼此獨立,不互相影響,實現模組間的鬆耦合。

1.每個類儘量都有介面或抽象類,或者抽象類和介面兩者都具備。這是依賴倒置的基本要求,介面和抽象類都是屬於抽象的,有了抽象才可能依賴倒置。

2.變數的表面型別儘量是介面或者是抽象類。在高層業務邏輯,它對低層模組的依賴都建立在抽象上,例如使用的IDriver和ICar這樣的抽象類。

3.任何類都不應該從具體類派生。

4.儘量不要覆寫基類的方法。

5.結合里氏替換原則使用。介面負責定義public屬性和方法,並且宣告與其他物件的依賴關係,抽象類負責公共構造部分的實現,實現類準確的實現業務邏輯,同時在適當的時候對父類進行細化。

介面隔離原則

定義:客戶端不應該依賴他不需要的介面;類間的依賴關係應該建立在最小的介面上。

概括:建立單一介面,不要建立臃腫龐大的介面。介面儘量細化,同時介面中的方法儘量少。

實踐:把一個臃腫的介面變更為兩個獨立的介面所依賴的原則就是介面隔離原則。介面是我們設計時對外提供的契約,通過分散定義多個介面,可以預防未來變更的擴散,提高系統的靈活性和可維護性。

原則:介面要儘量小;介面要高內聚;定製服務;介面設計是有限度的。

迪米特法則

定義:最少知識原則(LeastKnowledge Principle,LKP),一個物件應該對其他物件有最少的瞭解。

迪米特法則的核心觀念就是類間解耦,弱耦合,只有弱耦合了以後,類的複用率才可以提高。儘量不要對外公佈太多的public方法和非靜態的public變數,多使用private、package-private、protected等訪問許可權。

開閉原則

定義:一個軟體實體如類、模組和函式應該對擴充套件開放,對修改關閉。

變化歸納為以下三種類型:

1.邏輯變化。只變化一個邏輯,而不涉及其他模組,比如原有的一個演算法是ab+c,現在需要修改為ab*c,可以通過修改原有類中的方法的方式來完成,前提條件是所有依賴或關聯類都按照相同的邏輯處理。

2.子模組變化。一個模組變化,會對其他的模組產生影響,特別是一個低層次的模組變化必然引起高層模組的變化,因此在通過擴充套件完成變化時,高層次的模組修改是必然的。

3.可見檢視變化。可見檢視是提供給客戶使用的介面,還是可以通過擴充套件來完成變化。

實踐:

1.抽象約束。抽象是對一組事物的通用描述,沒有具體的實現,也就表示它可以有非常多的可能性,可以跟隨需求的變化而變化。。因此,通過介面或抽象類可以約束一組可能變化的行為,並且能夠實現對擴充套件開放,其包含三層含義:第一,通過介面或抽象類約束擴充套件,對擴充套件進行邊界限定,不允許出現在介面或抽象類中不存在的public方法;第二,引數型別、引用物件儘量使用介面或者抽象類,而不是實現類;第三,抽象層儘量保持穩定,一旦確定即不允許修改。

2.元資料(metadata)控制模組行為。儘量使用元資料來控制程式的行為,減少重複開發。元資料是用來描述環境和資料的資料,通俗地說就是配置引數,引數可以從檔案中獲得,也可以從資料庫中獲得。

3.制定專案章程。

4.封裝變化。對變化的封裝包含兩層含義:第一,將相同的變化封裝到一個介面或抽象類中;第二,將不同的變化封裝到不同的介面或抽象類中,不應該有兩個不同的變化出現在同一個介面或抽象類中。