天天看點

設計模式之(1)設計原則

*開-閉原則(Open-Closed Principle, OCP):一個軟體實體應當對擴充開發,對修改關閉.說的是,再設計一個子產品的時候,應當使這個子產品可以在不被修改的前提下被擴充.換言之,應當可以在不必修改源代碼的情況下改變這個子產品的行為.

*.UML(統一模組化語言, Unified Modeling Language),是OMG(Object Management Group)在1997年發表的圖示式軟體設計語言.

1.類圖中的關系:

(1).一般化關系:(Generalization)

    表示類與類之間的繼承關系,接口與接口之間的繼承關系,或類對接口的實作關系.一般化的關系是從子類指向父類的,或從實作接口的類指向被實作的接口.

(2).關聯關系:(Association)

    是類與類之間的聯接,它使一個類知道另一個類的屬性和方法.關聯可以是雙向的,也可以是單向的.雙向的關聯可以有兩個箭頭或者沒有箭頭.單向的關聯有一個箭頭,表示關聯的方向.單向的關聯更為普遍,通常不鼓勵使用雙向的箭頭.

(3).聚合關系:(Aggregation)

    是關聯關系的一種,是強的關聯關系.聚合是整體和個體之間的關系.

(4).合成關系:(Composition)

    是關聯關系的一種,是比聚合關系更強的關系.它要求普通的聚合關系中代表整體的對象負責代表部分的對象的生命周期,合成關系是不能共享的.

(5).依賴關系:(Dependency)

    也是類與類之間的聯接,依賴總是單向的.依賴關系表示一個類依賴于另一個類的定義.

2.時序圖(Sequence Diagram)

    有時又叫做序列圖/活動序列圖.作為互動圖的一種,序列互動圖按照時間順序從上往下顯示每個使用案例.在一個時序圖中,垂直的虛線叫做生命線,它代表一個對象存在的時間.每一個箭頭都是一個調用,這個箭頭從調用者對象連接配接到接收者對象的生命線上的激活條(Activation Bar)上.每一個激活條代表調用所持續的時間.

3.狀态圖(State Diagram)

     又稱做狀态轉換圖(State Transition Diagram).狀态圖的基本想法是定義一個具有有限個内部狀态的機器.是以狀态圖又稱做有限狀态機.對象被外界的事件激發,進而從一個狀态轉換到另一個狀态.

4.單一職責原則(Simple responsibility pinciple SRP)

就一個類而言,應該僅有一個引起它變化的原因,如果你能想到多于一個的動機去改變一個類,那麼這個類就具有多于一個的指責.應該把多于的指責分離出去,分别再建立一些類來完成每一個指責.

5.裡氏代換原則(Liskov Substitution Principle,常縮寫為.LSP)

(1).由Barbar Liskov(芭芭拉.裡氏)提出

(2).嚴格表達:如果每一個類型為T1的對象o1,都有類型為T2的對象o2,使得以T1定義的所有程式P在所有的對象o1都代換稱o2時,程式P的行為沒有變化,那麼類型T2是類型T1的子類型.

    換言之,一個軟體實體如果使用的是一個基類的話,那麼一定适用于其子類,而且它根本不能察覺出基類對象和子類對象的差別.

(3).反過來的代換不成立

(4).<墨子.小取>中說:"白馬,馬也; 乘白馬,乘馬也.骊馬(黑馬),馬也;乘骊馬,乘馬也."

(5).該類西方著名的例程為:正方形是否是長方形的子類(答案是"否")

(6).應當盡量從抽象類繼承,而不從具體類繼承,一般而言,如果有兩個具體類A,B有繼承關系,那麼一個最簡單的修改方案是建立一個抽象類C,然後讓類A和B成為抽象類C的子類.即如果有一個由繼承關系形成的登記結構的話,那麼在等級結構的樹形圖上面所有的樹葉節點都應當是具體類;而所有的樹枝節點都應當是抽象類或者接口.

(7)."基于契約設計(Design By Constract),簡稱DBC"這項技術對LISKOV代換原則提供了支援.該項技術Bertrand Meyer伯特蘭做過詳細的介紹:

使用DBC,類的編寫者顯式地規定針對該類的契約.客戶代碼的編寫者可以通過該契約獲悉可以依賴的行為方式.契約是通過每個方法聲明的前置條件(preconditions)和後置條件(postconditions)來指定的.要使一個方法得以執行,前置條件必須為真.執行完畢後,該方法要保證後置條件為真.就是說,在重新聲明派生類中的例程(routine)時,隻能使用相等或者更弱的前置條件來替換原始的前置條件,隻能使用相等或者更強的後置條件來替換原始的後置條件.

6.依賴倒轉原則(Dependence Inversion Principle),要求用戶端依賴于抽象耦合.

(1)表述:抽象不應當依賴于細節,細節應當依賴于抽象.(Program to an interface, not an implementaction)

(2)表述二:針對接口程式設計的意思是說,應當使用接口和抽象類進行變量的類型聲明,參量的類型聲明,方法的返還類型聲明,以及資料類型的轉換等.不要針對實作程式設計的意思就是說,不應當使用具體類進行變量的類型聲明,參量類型聲明,方法的返還類型聲明,以及資料類型的轉換等.

   要保證做到這一點,一個具體的類應等隻實作接口和抽象類中聲明過的方法,而不應當給出多餘的方法.

   隻要一個被引用的對象存在抽象類型,就應當在任何引用此對象的地方使用抽象類型,包括參量的類型聲明,方法返還類型的聲明,屬性變量的類型聲明等.

接口與抽象:

(3)接口與抽象的差別就在于抽象類可以提供某些方法的部分實作,而接口則不可以,這也大概是抽象類唯一的優點.如果向一個抽象類加入一個新的具體方法,那麼所有的子類型一下子就都得到得到了這個新的具體方法,而接口做不到這一點.如果向一個接口加入了一個新的方法的話,所有實作這個接口的類就全部不能通過編譯了,因為它們都沒有實作這個新聲明的方法.這顯然是接口的一個缺點.

(4)一個抽象類的實作隻能由這個抽象類的子類給出,也就是說,這個實作處在抽象類所定義出的繼承的登記結構中,而由于一般語言都限制一個類隻能從最多一個超類繼承,是以将抽象作為類型定義工具的效能大打折扣.

   反過來,看接口,就會發現任何一個實作了一個接口所規定的方法的類都可以具有這個接口的類型,而一個類可以實作任意多個接口.

(5)從代碼重構的角度上講,将一個單獨的具體類重構成一個接口的實作是很容易的,隻需要聲明一個接口,并将重要的方法添加到接口聲明中,然後在具體類定義語句中加上保留字以繼承于該接口就行了.

   而作為一個已有的具體類添加一個抽象類作為抽象類型不那麼容易,因為這個具體類有可能已經有一個超類.這樣一來,這個新定義的抽象類隻好繼續向上移動,變成這個超類的超類,如此循環,最後這個新的抽象類必定處于整個類型等級結構的最上端,進而使登記結構中的所有成員都會受到影響.

(6)接口是定義混合類型的理想工具,所為混合類型,就是在一個類的主類型之外的次要類型.一個混合類型表明一個類不僅僅具有某個主類型的行為,而且具有其他的次要行為.

(7)聯合使用接口和抽象類:

   由于抽象類具有提供預設實作的優點,而接口具有其他所有優點,是以聯合使用兩者就是一個很好的選擇.

   首先,聲明類型的工作仍然接口承擔的,但是同時給出的還有一個抽象類,為這個接口給出一個預設實作.其他同屬于這個抽象類型的具體類可以選擇實作這個接口,也可以選擇繼承自這個抽象類.如果一個具體類直接實作這個接口的話,它就必須自行實作所有的接口;相反,如果它繼承自抽象類的話,它可以省去一些不必要的的方法,因為它可以從抽象類中自動得到這些方法的預設實作;如果需要向接口加入一個新的方法的話,那麼隻要同時向這個抽象類加入這個方法的一個具體實作就可以了,因為所有繼承自這個抽象類的子類都會從這個抽象類得到這個具體方法.這其實就是預設擴充卡模式(Defaule Adapter).

(8)什麼是高層政策呢?它是應用背後的抽象,是那些不随具體細節的改變而改變的真理. 它是系統内部的系統____隐喻.

7.接口隔離原則(Interface Segregation Principle, ISP)

使用多個專門的接口比使用單一的總接口要好.根據客戶需要的不同,而為不同的用戶端提供不同的服務是一種應當得到鼓勵的做法.就像"看人下菜碟"一樣,要看客人是誰,再提供不同檔次的飯菜.

胖接口會導緻他們的客戶程式之間産生不正常的并且有害的耦合關系.當一個客戶程式要求該胖接口進行一個改動時,會影響到所有其他的客戶程式.是以客戶程式應該僅僅依賴他們實際需要調用的方法.

8.合成/聚合複用原則(Composite/Aggregate Reuse Principle,CARP)

在一個新的對象裡面使用一些已有的對象,使之成為新對象的一部分;新的對象通過這些向對象的委派達到複用已有功能的目的.這個設計原則有另一個簡短的表述:要盡量使用合成/聚合,盡量不要使用繼承.

9.迪米特法則(Law of Demeter LoD)又叫做最少隻是原則(Least Knowledge Principle,LKP),就是說,一個對象應當對其他對象有盡可能少的了了解.

迪米特法則最初是用來作為面向對象的系統設計風格的一種法則,與1987年秋天由Ian Holland在美國東北大學為一個叫做迪米特(Demeter)的項目設計提出的,是以叫做迪米特法則[LIEB89][LIEB86].這條法則實際上是很多著名系統,比如火星登陸軟體系統,木星的歐羅巴衛星軌道飛船的軟體系統的指導設計原則.

沒有任何一個其他的OO設計原則象迪米特法則這樣有如此之多的表述方式,如下幾種:

(1)隻與你直接的朋友們通信(Only talk to your immediate friends)

(2)不要跟"陌生人"說話(Don't talk to strangers)

(3)每一個軟體機關對其他的機關都隻有最少的隻是,而且局限于那些本機關密切相關的軟體機關.

就是說,如果兩個類不必彼此直接通信,那麼這兩個類就不應當發生直接的互相作用,如果其中的一個類需要調用另一個類的某一個方法的話,可以通過第三者轉發這個調用.

繼續閱讀