面向對象設計原則二

  1. 單一職責原則(SRP):一個類應當只有一個改變的原因,類只需要知道一件事情,它們應當有一個單獨的職責,要點就是當一個類需要改變時,應當只有一個原因。
  2. 開放-封閉原則(OCP):軟件實體(類、模塊、函數等)應當爲擴展而開放,又爲修改而封閉。這個原則有一個相當詳細的定義,但是一個簡單的意思是:你應當能夠改變一個模塊的周邊環境而無須改變模塊本身。
  3. Liskov替換原則(LSP):子類型(subtypes)必須是爲它們的基類型(base types)可替代的。
  4. 依存關係倒置原則(DIP) :A.高層模塊應當不依賴低層模塊,它們應當依賴於抽象。
    B.抽象應當不依賴於細節,細節應當依賴於抽象。
    更好的描述是:不要依賴那些容易變化的具體類。如果你要繼承一個類,從一個抽象類繼承吧。如果你要持有一個類的引用,從一個抽象的類引用吧。如果你要調用一個函數,從一個抽象的函數調用吧。
  5. 接口隔離原則(ISP):客戶不應當依賴那些它們根本不用的方法。

總結:
五個簡單的原則是:
1、SRP--一個類應當只有一個發生變化的原因。
2、OCP――應當能夠改變一個類的環境,而無須改變類本身。
3、LSP――避免造成派生類的方法非法或退化,一個基類的用戶應當不需要知道這個派生類。
4、DIP ――用依賴於接口和抽象類來替代依賴容易變化的具體類。
5、ISP――給一個對象的每一個用戶一個接口,這個接口僅有用戶需要的方法。


正 如牛頓三大定律在經典力學中的位置一樣,“開-閉”原則(Open-Closed Principle)是面向對象的可複用設計(Object Oriented Design或OOD)的基石。其他設計原則(里氏代換原則、依賴倒轉原則、合成/聚合複用原則、迪米特法則、接口隔離原則)是實現“開-閉”原則的手段 和工具。
  一、“開-閉”原則(Open-Closed Principle,OCP)
   1.1“開-閉”原則的定義及優點
   1)定義:一個軟件實體應當對擴展開放,對修改關閉( Software entities should be open for extension,but closed for modification.)。即在設計一個模塊的時候,應當使這個模塊可以在不被修改的前提下被擴展。
  2)滿足“開-閉”原則的系統的優點
  a)通過擴展已有的軟件系統,可以提供新的行爲,以滿足對軟件的新需求,使變化中的軟件系統有一定的適應性和靈活性。
  b)已有的軟件模塊,特別是最重要的抽象層模塊不能再修改,這就使變化中的軟件系統有一定的穩定性和延續性。
  c)這樣的系統同時滿足了可複用性與可維護性。
  1.2如何實現“開-閉”原則
  在面向對象設計中,不允許更改的是系統的抽象層,而允許擴展的是系統的實現層。換言之,定義一個一勞永逸的抽象設計層,允許儘可能多的行爲在實現層被實現。
  解決問題關鍵在於抽象化,抽象化是面向對象設計的第一個核心本質。
  對一個事物抽象化,實質上是在概括歸納總結它的本質。抽象讓我們抓住最最重要的東西,從更高一層去思考。這降低了思考的複雜度,我們不用同時考慮那麼多的東西。換言之,我們封裝了事物的本質,看不到任何細節。
  在面向對象編程中,通過抽象類及接口,規定了具體類的特徵作爲抽象層,相對穩定,不需更改,從而滿足“對修改關閉”;而從抽象類導出的具體類可以改變系統的行爲,從而滿足“對擴展開放”。[Page]
  對實體進行擴展時,不必改動軟件的源代碼或者二進制代碼。關鍵在於抽象。
  1.3對可變性的封裝原則
   “開-閉”原則也就是“對可變性的封裝原則”(Principle of Encapsulation of Variation ,EVP)。即找到一個系統的可變因素,將之封裝起來。換言之,在你的設計中什麼可能會發生變化,應使之成爲抽象層而封裝,而不是什麼會導致設計改變才封 裝。
   “對可變性的封裝原則”意味着:
  a)一種可變性不應當散落在代碼的許多角落,而應當被封裝到一個對象裏面。同一可變性的不同表象意味着同一個繼承等級結構中的具體子類。因此,此處可以期待繼承關係的出現。繼承是封裝變化的方法,而不僅僅是從一般的對象生成特殊的對象。
  b)一種可變性不應當與另一種可變性混合在一起。作者認爲類圖的繼承結構如果超過兩層,很可能意味着兩種不同的可變性混合在了一起。
  使用“可變性封裝原則”來進行設計可以使系統遵守“開-閉”原則。
  即使無法百分之百的做到“開-閉”原則,但朝這個方向努力,可以顯著改善一個系統的結構。
  二、里氏代換原則(Liskov Substitution Principle, LSP)
  2.1概念
  定義:如果對每一個類型爲T1的對象O1,都有類型爲T2 的對象O2,使得以T1定義的所有程序P在所有的對象O1都代換爲O2時,程序P的行爲沒有變化,那麼類型T2是類型T1的子類型。
  即,一個軟件實體如果使用的是一個基類的話,那麼一定適用於其子類。而且它覺察不出基類對象和子類對象的區別。也就是說,在軟件裏面,把基類都替換成它的子類,程序的行爲沒有變化。
  反過來的代換不成立,如果一個軟件實體使用的是一個子類的話,那麼它不一定適用於基類。
  任何基類可以出現的地方,子類一定可以出現。
  基於契約的設計、抽象出公共部分作爲抽象基類的設計。
  2.2里氏代換原則與“開-閉”原則的關係
   實現“開-閉”原則的關鍵步驟是抽象化。基類與子類之間的繼承關係就是抽象化的體現。因此里氏代換原則是對實現抽象化的具體步驟的規範。
   違反里氏代換原則意味着違反了“開-閉”原則,反之未必。
  三、 依賴倒轉原則(dependence inversion principle, DIP)
   3.1概念
    依賴倒轉原則就是要依賴於抽象,不要依賴於實現。(Abstractions should not depend upon details. Details should depend upon abstractions.)要針對接口編程,不要針對實現編程。(Program to an interface, not an implementation.)
  也就是說應當使用接口和抽象類進行變量類型聲明、參數類型聲 明、方法返還類型說明,以及數據類型的轉換等。而不要用具體類進行變量的類型聲明、參數類型聲明、方法返還類型說明,以及數據類型的轉換等。要保證做到這 一點,一個具體類應當只實現接口和抽象類中聲明過的方法,而不要給出多餘的方法。
  傳統的過程性系統的設計辦法傾向於使高層次的模塊依賴於低層次的模塊,抽象層次依賴於具體層次。倒轉原則就是把這個錯誤的依賴關係倒轉過來。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章