1. 程式人生 > >結構型設計模式對比 設計模式(十六)

結構型設計模式對比 設計模式(十六)

結構型設計模式 結構型模式關注於整體最終的結構,通過繼承和組合,構建出更加複雜的結構 進而提供更加強大的邏輯功能 七種結構型模式
  • 介面卡模式(Adapter Pattern)
  • 組合模式(Composite Pattern)
  • 裝飾器模式(Decorator Pattern)
  • 代理模式(Proxy Pattern) 
  • 橋接模式(Bridge Pattern)
  • 外觀模式(Facade Pattern)
  • 享元模式(Flyweight Pattern)
所有的結構型設計模式在邏輯上都各自不同程度的隱含了“間接”“代理”“委託”的含義 ,有的明顯,有的含蓄
  image_5c09c064_5021   強表現 介面卡、裝飾器、代理、組合、橋接模式,這幾種模式比較強烈的表現了“間接”“代理”“委託”的含義  從圖中可以清楚地看得出來,他們都有“代理”的含義
介面卡模式,通過繼承或者組合方式,“代理”了,被適配角色Adaptee
裝飾器模式,通過組合的方式,"是你還有你",內部擁有Component,代理了被裝飾的具體構建 ConcreteComponent
代理模式,通過組合的方式,內部擁有RealSubject,代理了真實主題角色
組合模式,通過組合的方式,內部包含葉子節點或者樹枝節點,內部“代理”了 子物件
橋接模式,通過組合的方式,內部擁有Implementor,指向實現者
  如果裝飾器模式只有一個被裝飾的類ConcreteComponent,也只有一個裝飾器角色ConcreteDecorator 省略掉Decorator ,他跟代理模式的結構可以說是一樣的 省略掉裝飾器模式結構圖中的ConcreteDecorator角色,組合模式和裝飾器模式的結構就完全一樣了 如果只有一種型別的ConcreteImplementor,橋接模式又與物件介面卡模式相同   雖然說他們都有“代理”的含義,但是他們又有很大差別
介面卡模式下,“代理”的物件是功能相近的替代方案,比如,插座介面卡可以進行插頭轉換
使得原本不相容,不能夠一起工作的那些類能夠一起工作
代理模式下,“代理”的真實主題的物件RealSubject,從而 對真實物件進行隱藏,封裝 透明的對外界提供服務,控制外界對這個物件的訪問
裝飾器模式下,“代理”的是抽象的Component構建,能夠代理所有的ConcreteComponent型別
裝飾器和被裝飾的構建都是Component,重點在於功能的擴充套件,新增額外的職責
組合模式下,“代理”的是抽象構建Component,代理的是子物件,用於描述“整體-部分”的概念
橋接模式,“代理”的是實現角色Implementor,代理的是具體的實現,用於將抽象與實現進行分離
分離後通過橋接模式進行連線
他們雖然都是“代理”,但是他們的側重點不同,被代理的事物的性質不同 介面卡模式在代理的過程中,重點在於適配,不會增加額外的功能 代理模式側重於控制,當然也通常用於增加功能 如果代理模式,代理的不是真實主題物件RealSubject,而是抽象構建Subject,顯然,就演化成了裝飾器模式 因為代理模式不光能夠控制外界對真實物件的訪問,他也能夠提供額外的服務 裝飾器模式則是重點在於功能的擴充套件,增肌額外的職責 而組合模式,重點在於形成“整體--部分”的結構,並且對外界客戶端程式,提供一致的訪問形式   弱表現 享元模式和外觀模式也是一定程度的代理 享元模式,通過內部狀態與外部狀態的分離,通過享元池中的享元物件,代理了所有的具有內外狀態完整的物件 對客戶端來說就是有如此多的物件, 只不過記憶體中卻僅有少量的物件   外觀模式在結構上完全看不出來“代理”的含義,但是他在業務邏輯上充當的也恰恰是“介面人”“協調者”“控制檯”的角色 所以也可以認為是“代理”了內部的子系統   代理模式與介面卡模式 代理模式和介面卡模式都需要藉助於內部的“被代理”物件,或者“被適配者”物件進行工作 也就是說他們都將自己的工作委託出去   但是代理模式中, 代理者與被代理者他們擁有相同的介面,也就是擁有相同的對外呈現,重點在於對真實物件的隱藏,客戶端請求的透傳,並且可以額外的增加一些控制,管理 介面卡模式中,目標物件和被適配者在介面上沒有必然聯絡,比如目標是港版插座面板,被適配者是大陸插座面板,他們的共同點是提供電力,但是介面卻完全不同 介面卡的重點在於不能一起工作的類能夠一起工作   代理模式與裝飾器模式 代理模式提供與被代理的真實物件相同的訪問介面,對真實物件進行一定的控制,也可以增加額外的服務,職責 裝飾器模式也是代理了內部真實的物件,並且擁有相同的訪問介面   但是代理模式重點在於增加對真實物件的控制,隱藏真實物件,一般會在代理類內部建立一個真實的物件 也就是說這種 代理關係在編譯時期已經靜態確定了 代理類接受處理來自客戶端的請求,在內部轉發到真實主題物件上 比如
//代理模式
public class Proxy implements Subject{
private Subject realSubject;
public Proxy(){
//關係在編譯時確定
realSubject = new RealSubject();
}
public void doSth(){
….
realSubject.doSth();
….
}
}
裝飾器模式在於功能的動態增加,所以物件一般作為引數進行傳遞,比如:       InputStream inputStream = new BufferedInputStream(new FileInputStream("........")); 這是一種在 執行期間動態增加功能方式   介面卡與外觀模式 介面卡模式將一種介面轉換為另外一種介面,使得原本不能一起工作的類可以協作 外觀模式是將子系統的的多個介面的訪問轉換為另一種介面,使得原本複雜難用,耦合程度高的多個類有一個一致簡單的介面 他們都變成了另外一種形式的介面 所有的請求也都是委託他人進行處理,介面卡模式委託給被適配角色,外觀模式委託給子系統   介面卡模式是為了能夠一起工作,他們原本是並不相容的 外觀模式是為了能夠更好地更簡單的工作,他們原本是可以一起工作的   橋接模式與介面卡模式 介面卡模式的主要目的是讓因為介面不相容而不能互相工作的類能夠一起工作 換句話說就是 他們本身不同,我用“紐帶” Adapter將他們連線起來
橋接模式則是將原本或許緊密結合在一起的抽象與實現,進行分離 使她們能夠各自獨立的發展,是把連線在一起的兩個事物,拆分開來 然後用“紐帶”“橋樑”(也就是物件的引用)將他們連線起來
介面卡模式就好比 張三和王五不認識,李四介紹他們認識 橋樑模式好比張三和王五成天黏在一起活幹得不好太亂套,李四說以後我作為介面人,你倆各幹各的吧 雖然看起來都是兩個人幹活,中間一個聯絡人,但是含義卻是完全不同
橋接模式與裝飾器模式 裝飾器模式中,使用組合而不是繼承來對類的功能進行擴充套件 避免了類的個數的爆炸增長, 與橋樑模式的結果不約而同 他們 都解決了類爆炸增長的問題,都避免了過多的沒必要的子類
裝飾器模式側重於功能的動態增加,將額外的功能提取到子類中 通過不同的排列組合,形成一個遞迴的呼叫方式,以動態的增加各部分的功能
橋樑模式是將原本系統中的實現細節抽取出來,比如原來抽象概念與例項化全部都是一個類層次結構中 把所有的實現細節,比如示例中的平臺相關實現,抽取出來,進行分離達到抽象與實現分離的目的
所以雖然他們都可以解決子類爆炸式增長、不易擴充套件的問題 但是他們的 出發點完全不同 一個關注於功能的動態擴充套件組合 一個關注於抽象與實現的分離,獲得更多的靈活性     總結 所有的結構型模式的都離不開“分離,解耦”的概念 而“分離,解耦”之後,又通過某種形式建立聯絡,比如“組合” 抽象與實現進行分離,分離就意味著獨立,獨立就意味著可以單獨發展,橋接模式 對於分離的事物通過委託的形式託付工作,就可以在中間提供更多的服務,代理模式 而分離的兩個事物也可以通過一定形式的結合、轉換進而一起協同工作,介面卡模式 將一個物件的多個功能點進行分離,從而能夠動態的組合以形成更強大的功能,裝飾器模式 將事物自身內部核心狀態與外部狀態進行分離,進而減少核心狀態的儲存執行消耗,享元模式 將客戶端與子系統的耦合互動進行分離,抽象出來一個新的接入點,外觀Facade,降低耦合,外觀模式 分離開的多種事物,如果他們有“整體--部分”的關係,可以將它們組合在一起,形成更復雜的整體結構,組合模式 (ps:上面的分離指分開的,不耦合在一起,不是特指原本是一個整體,被分成兩部分)   以上各個部分的差異對比點主要根據設計模式的最初意圖、動機,設計模式本就是設計原則的實現化角色 對於任何的結構,你都可以按照你自己的想法去使用、拓展,當然,前提是更合適或者更優秀 否則您那是瞎用 比如代理模式與裝飾器模式本就很類似,如果你將代理模式的真實物件也是作為引數進行傳遞 也是用來動態的增加職責,那麼就成了裝飾器模式,所以再回頭,你說你的是代理模式還是裝飾器模式? 這麼看這個名字代理還是裝飾器又有什麼大的區別的呢?都只是用來敘述而已 但是如果你這麼做還非要說是代理模式,有一個很大的問題就是和同事、領導溝通起來就特別費勁了,說不定還會吵起來... 所以,除非你有更好更合適的選擇,或者改變 否則,一定要儘量按照模式原本的意圖和動機去使用某種模式   原文地址: 結構型設計模式對比 設計模式(十六)