面向對象設計原則三

  面向對象設計的重要原則是創建抽象化,並且從抽象化導出具體化,具體化給出不同的實現。繼承關係就是一種從抽象化到具體化的導出。[Page]
  抽象層包含的應該是應用系統的商務邏輯和宏觀的、對整個系統來說重要的戰略性決定,是必然性的體現。具體層次含有的是一些次要的與實現有關的算法和邏輯,以及戰術性的決定,帶有相當大的偶然性選擇。具體層次的代碼是經常變動的,不能避免出現錯誤。
  從複用的角度來說,高層次的模塊是應當複用的,而且是複用的重點,因爲它含有一個應用系統最重要的宏觀商務邏輯,是較爲穩定的。而在傳統的過程性設計中,複用則側重於具體層次模塊的複用。
  依賴倒轉原則則是對傳統的過程性設計方法的“倒轉”,是高層次模塊複用及其可維護性的有效規範。
  特例:對象的創建過程是違背“開—閉”原則以及依賴倒轉原則的,但通過工廠模式,能很好地解決對象創建過程中的依賴倒轉問題。
  3.2關係
  “開-閉”原則與依賴倒轉原則是目標和手段的關係。如果說開閉原則是目標,依賴倒轉原則是到達/"開閉/"原則的手段。如果要達到最好的/"開閉/"原則,就要儘量的遵守依賴倒轉原則,依賴倒轉原則是對/"抽象化/"的最好規範。
  里氏代換原則是依賴倒轉原則的基礎,依賴倒轉原則是里氏代換原則的重要補充。
  3.3耦合(或者依賴)關係的種類:
  零耦合(Nil Coupling)關係:兩個類沒有耦合關係
  具體耦合(Concrete Coupling)關係:發生在兩個具體的(可實例化的)類之間,經由一個類對另一個具體類的直接引用造成。
  抽象耦合(Abstract Coupling)關係:發生在一個具體類和一個抽象類(或接口)之間,使兩個必鬚髮生關係的類之間存有最大的靈活性。
  3.3.1如何把握耦合
  我們應該儘可能的避免實現繼承,原因如下:
  1 失去靈活性,使用具體類會給底層的修改帶來麻煩。
   2 耦合問題,耦合是指兩個實體相互依賴於對方的一個量度。程序員每天都在(有意識地或者無意識地)做出影響耦合的決定:類耦合、API耦合、應用程序耦合等 等。在一個用擴展的繼承實現系統中,派生類是非常緊密的與基類耦合,而且這種緊密的連接可能是被不期望的。如B extends A ,當B不全用A中的所有methods時,這時候,B調用的方法可能會產生錯誤!
  我們必須客觀的評價耦合度,系統之間不可能總是松耦合的,那樣肯定什麼也做不了。
  3.3.2我們決定耦合的程度的依據何在呢?
   簡單的說,就是根據需求的穩定性,來決定耦合的程度。對於穩定性高的需求,不容易發生變化的需求,我們完全可以把各類設計成緊耦合的(我們雖然討論類之 間的耦合度,但其實功能塊、模塊、包之間的耦合度也是一樣的),因爲這樣可以提高效率,而且我們還可以使用一些更好的技術來提高效率或簡化代碼,例如c# 中的內部類技術。可是,如果需求極有可能變化,我們就需要充分的考慮類之間的耦合問題,我們可以想出各種各樣的辦法來降低耦合程度,但是歸納起來,不外乎 增加抽象的層次來隔離不同的類,這個抽象層次可以是抽象的類、具體的類,也可以是接口,或是一組的類。我們可以用一句話來概括降低耦合度的思想:/"針對 接口編程,而不是針對實現編程。
  在我們進行編碼的時候,都會留下我們的指紋,如public的多少,代碼的格式等等。我們可以耦合度量評估重 新構建代碼的風險。因爲重新構建實際上是維護編碼的一種形式,維護中遇到的那些麻煩事在重新構建時同樣會遇到。我們知道在重新構建之後,最常見的隨機 bug大部分都是不當耦合造成的 。[Page]
  如果不穩定因素越大,它的耦合度也就越大。
  某類的不穩定因素=依賴的類個數/被依賴的類個數
  依賴的類個數= 在編譯此類的時被編譯的其它類的個數總和
  3.3.3怎樣將大系統拆分成小系統
  解決這個問題的一個思路是將許多類集合成一個更高層次的單位,形成一個高內聚、低耦合的類的集合,這是我們設計過程中應該着重考慮的問題!
  耦合的目標是維護依賴的單向性,有時我們也會需要使用壞的耦合。在這種情況下,應當小心記錄下原因,以幫助日後該代碼的用戶瞭解使用耦合真正的原因。
  3.4怎樣做到依賴倒轉?
  以抽象方式耦合是依賴倒轉原則的關鍵。抽象耦合關係總要涉及具體類從抽象類繼承,並且需要保證在任何引用到基類的地方都可以改換成其子類,因此,里氏代換原則是依賴倒轉原則的基礎。
  在抽象層次上的耦合雖然有靈活性,但也帶來了額外的複雜性,如果一個具體類發生變化的可能性非常小,那麼抽象耦合能發揮的好處便十分有限,這時可以用具體耦合反而會更好。
  層次化:所有結構良好的面向對象構架都具有清晰的層次定義,每個層次通過一個定義良好的、受控的接口向外提供一組內聚的服務。
  依賴於抽象:建議不依賴於具體類,即程序中所有的依賴關係都應該終止於抽象類或者接口。儘量做到:
  1、任何變量都不應該持有一個指向具體類的指針或者引用。
  2、任何類都不應該從具體類派生。
  3、任何方法都不應該覆寫它的任何基類中的已經實現的方法。
  3.5依賴倒轉原則的優缺點
  依賴倒轉原則雖然很強大,但卻最不容易實現。因爲依賴倒轉的緣故,對象的創建很可能要使用對象工廠,以避免對具體類的直接引用,此原則的使用可能還會導致產生大量的類,對不熟悉面向對象技術的工程師來說,維護這樣的系統需要較好地理解面向對象設計。
  依賴倒轉原則假定所有的具體類都是會變化的,這也不總是正確。有一些具體類可能是相當穩定,不會變化的,使用這個具體類實例的應用完全可以依賴於這個具體類型,而不必爲此創建一個抽象類型。
  四、合成/聚合複用原則(Composite/Aggregate Reuse Principle或CARP)
   4.1概念
  定義:在一個新的對象裏面使用一些已有的對象,使之成爲新對象的一部分;新的對象通過向這些對象的委派達到複用這些對象的目的。
  應首先使用合成/聚合,合成/聚合則使系統靈活,其次才考慮繼承,達到複用的目的。而使用繼承時,要嚴格遵循里氏代換原則。有效地使用繼承會有助於對問題的理解,降低複雜度,而濫用繼承會增加系統構建、維護時的難度及系統的複雜度。
  如果兩個類是“Has-a”關係應使用合成、聚合,如果是“Is-a”關係可使用繼承。/"Is-A/"是嚴格的分類學意義上定義,意思是一個類是另一個類的/"一種/"。而/"Has-A/"則不同,它表示某一個角色具有某一項責任。

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