結構型
適配器
將一個類的介面轉換成客戶希望的另一個介面。適配器模式使得原來由於介面不相容而不能一起工作的類可以一起工作。
物件導向的精神就是更好的應對需求的變化,而現實中往往會有下面這些情況:想使用一個已經存在的類,而它的介面不符合要求,或者希望建立一個可以複用的類,該類可以與其他不相關的類或不可預見的類協同工作。遵循“對修改關閉,對擴充開放”的原則,讓這些介面不同的類通過適配器後,協同工作。
適配器模式主要是為瞭解決兩個已有介面之間不匹配的問題,它不需要考慮這些介面是怎樣實現的,也不考慮它們各自可能會如何演化。這種方式不需要對兩個獨立設計的類中任何一個進行重新設計,就能夠使它們協同工作。
橋接
將抽象部分與它的實現部分分離,使它們可以獨立地變化。
繼承是好的東西,但往往會過度地使用,繼承會導致類的結構過於複雜,關係太多,難以維護,而更糟糕的是擴充性非常差。而仔細研究如果能發現繼承體系中,有兩個甚至多個方向的變化,那麼就解耦這些不同方向的變化,通過對象組合的方式,把兩個角色之間的繼承關係改為了組合的關係,從而使這兩者可以應對各自獨立的變化,遵循合成/彙總複用的原則,找出變化並封裝之。
橋接和適配器有一些共同之處,就是給另一對象提供一定程度的間接性,這樣可以有利於系統的靈活性。但是橋接通常是在設計之初就對抽象介面與它的實現部分進行橋接,讓抽象與實現兩者可以獨立演化。
橋接和裝飾被應用於軟體生命週期的不同階段,針對的是不同的問題。
外觀(迪米特法則)
為子系統中的一組介面提供一個一致的介面,面板模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。
資訊的隱藏促進了軟體的複用。類之間的耦合越弱,越有利於複用,一個處在弱耦合的類被修改,不會對有關係的類造成波及。如果兩個類不必彼此直接通訊,那麼就不要讓這兩個類發生直接相互作用。如果實在需要調用,可以通過第三者來轉寄調用。
應該讓一個軟體中的子系統間的通訊和相互依賴關係達到最小,而具體辦法就是引入一個外觀對象,它為子系統間提供了一個單一而簡單的屏障。
外觀與適配器也有一些近似,都是對現存系統的封裝。外觀定義的是一個新的介面,而適配器則是複用一個原有的介面,適配器是使用兩個原有的介面協同工作,而外觀則是為現存系統提供一個更為方便的提供者。適配器是用來適配對象的,而外觀則是用來適配整個子系統的,外觀所針對的對象的粒度更大。
組合
將對象組合成樹形結構以表示“部分-整體”的階層,組合模式使得使用者對單個對象和組合對象的使用具有一致性。
使用者使用組合類別介面與組合結構中的對象進行互動,如果接收者是一個分葉節點,則直接處理請求,如果接收者是組合對象,通常將請求發送給它的子組件,並在轉寄請求之前或之後可能執行一些輔助操作。組合模式的效果是客戶可以一致地使用組合結構和單個對象。任何用到基本對象的地方都可以使用組合對象。
裝飾(合成/彙總複用)
動態地給一個對象添加一些額外的職責。就增加功能來說,裝飾模式相比產生子類更加靈活。
面對變化,如果採用產生子類的方法進行擴充,為支援每一種擴充的組合,會產生大量的子類,使得子類數目呈爆炸性增長,這是繼承所帶來的災難,而事實上,這些子類多半隻是為某個對象增加一些職責,此時通過裝飾的方式,可以更加靈活,以動態、透明的方式給單個對象添加職責,並在不需要時撤銷相應的職責。
享元(單一職責)
運用共用技術有效地支援大量細粒度的對象。
對象使得記憶體開銷過大,而且如果都是大量重複的對象,那就是資源的極大浪費,會使得機器效能減慢,這個顯然是不行的。
物件導向技術有時會因簡單化的設計而代價極大。享元模式可以避免大量非常相似類的開銷。在程式設計中,有時需要產生大量細粒度的類執行個體來表示資料。如果能發現這些執行個體除了幾個參數外基本上都是相同的,有時就能夠大幅度地減少需要執行個體化的類的數量。如果能把那些參數移動到類執行個體的外面,在方法調用時將它們傳遞進來,就可以通過共用大幅度地減少單個執行個體的數目。
代理(迪米特)
為其他對象提供一種代理以控制對這個對象的訪問。
代理與外觀的區別:
代理對象代表一個單一對象,而外觀對象代表一個子系統;代理的客戶對象無法直接存取目標對象,由代理提供對單獨的目標對象的存取控制,而外觀的客戶對象可以直接方位呢子系統中的各個對象,但通常由外觀對象提供對子系統各元件功能的簡化的共同層次的調用介面。
代理與適配器的區別:
代理是一種原來對象的代表,其他需要與這個對象打交道的操作都是和這個代表交涉。而適配器則不需要虛構出一個代表者,只需要為應付特定使用目的,將原來的類進行一些組合。