前言 這篇博客主要介紹23種設計模式的適用範圍以及他們的優缺點,類圖儘量使用了實例的類圖來替代,沒有找到的類圖就用了設計模式本身的結構圖。 創建型模式 抽象工廠模式 提供一個創建產品的介面來負責創建相關或依賴的對象,而不具體明確指定具體類 優點: 抽象工廠模式將具體產品的創建延遲到具體工廠的子類中, ...
前言
這篇博客主要介紹23種設計模式的適用範圍以及他們的優缺點,類圖儘量使用了實例的類圖來替代,沒有找到的類圖就用了設計模式本身的結構圖。
創建型模式
抽象工廠模式
提供一個創建產品的介面來負責創建相關或依賴的對象,而不具體明確指定具體類
優點:
抽象工廠模式將具體產品的創建延遲到具體工廠的子類中,這樣將對象的創建封裝起來,可以減少客戶端與具體產品類之間的依賴,從而使系統耦合度低,這樣更有利於後期的維護和擴展。
缺點:
抽象工廠模式很難支持新種類產品的變化。這是因為抽象工廠介面中已經確定了可以被創建的產品集合,如果需要添加新產品,此時就必須去修改抽象工廠的介面,這樣就涉及到抽象工廠類的以及所有子類的改變,這樣也就違背了“開發——封閉”原則。
適用場景:
①一個系統不應當依賴於產品類實例如何被創建、組合和表達的細節。
②系統中有多於一個的產品族,而每次只使用其中某一產品族。
③屬於同一個產品族的產品將在一起使用,這一約束必須在系統的設計中體現出來。
④產品等級結構穩定,設計完成之後,不會向系統中增加新的產品等級結構或者刪除已有的產品等級結構。
建造者模式
將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。建造者模式的本質是使組裝過程(用指揮者類進行封裝,從而達到解耦的目的)和創建具體產品解耦,使我們不用去關心每個組件是如何組裝的。
建造者模式的實現:
①在建造者模式中,指揮者是直接與客戶端打交道的,指揮者將客戶端創建產品的請求劃分為對各個部件的建造請求,再將這些請求委派到具體建造者角色,具體建造者角色是完成具體產品的構建工作的,卻不為客戶所知道。
②建造者模式主要用於“分步驟來構建一個複雜的對象”,其中“分步驟”是一個固定的組合過程,而複雜對象的各個部分是經常變化的(也就是說電腦的內部組件是經常變化的,這裡指的的變化如硬碟的大小變了,CPU由單核變雙核等)。
③產品不需要抽象類,由於建造模式的創建出來的最終產品可能差異很大,所以不大可能提煉出一個抽象產品類。
④在前面文章中介紹的抽象工廠模式解決了“系列產品”的需求變化,而建造者模式解決的是 “產品部分” 的需要變化。
⑤由於建造者隱藏了具體產品的組裝過程,所以要改變一個產品的內部表示,只需要再實現一個具體的建造者就可以了,從而能很好地應對產品組成組件的需求變化。
工廠方法模式
定義一個用於創建對象的介面,讓子類決定將哪一個類實例化。工廠方法模式讓一個類的實例化延遲到其子類。工廠方法模式又簡稱為工廠模式(Factory Pattern),又可稱作虛擬構造器模式(VirtualConstructor Pattern)或多態工廠模式(Polymorphic FactoryPattern)。
工廠方法模式之所以可以解決簡單工廠的模式,是因為它的實現把具體產品的創建推遲到子類中,此時工廠類不再負責所有產品的創建,而只是給出具體工廠必須實現的介面,這樣工廠方法模式就可以允許系統不修改工廠類邏輯的情況下來添加新產品,這樣也就剋服了簡單工廠模式中缺點。如果系統需要添加新產品時,我們可以利用多態性來完成系統的擴展,對於抽象工廠類和具體工廠中的代碼都不需要做任何改動。
原型模式
用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。
優點:
①原型模式向客戶隱藏了創建新實例的複雜性
②原型模式允許動態增加或較少產品類。
③原型模式簡化了實例的創建結構,工廠方法模式需要有一個與產品類等級結構相同的等級結構,而原型模式不需要這樣。
④產品類不需要事先確定產品的等級結構,因為原型模式適用於任何的等級結構
缺點:
①每個類必須配備一個克隆方法
②配備克隆方法需要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不一定很容易,特別當一個類引用不支持串列化的間接對象,或者引用含有迴圈結構的時候。
單例模式
確保某一個類只有一個實例,而且自行實例化並向整個系統提供這個實例,這個類稱為單例類,它提供全局訪問的方法。
優點:
①單例模式具有一定的伸縮性,類自己來控制實例化進程,類就在改變實例化進程上有相應的伸縮性。
②由於在系統記憶體中只存在一個對象,因此可以節約系統資源,當需要頻繁創建和銷毀的對象時單例模式無疑可以提高系統的性能。
③避免對共用資源的多重占用。
缺點:
①不適用於變化的對象,如果同一類型的對象總是要在不同的用例場景發生變化,單例就會引起數據的錯誤,不能保存彼此的狀態。
②由於單利模式中沒有抽象層,因此單例類的擴展有很大的困難。
③單例類的職責過重,在一定程度上違背了“單一職責原則”。
適用場景:
單例模式只允許創建一個對象,因此節省記憶體,加快對象訪問速度,因此對象需要被公用的場合適合使用,如多個模塊使用同一個數據源連接對象等等。
結構型模式
適配器模式
將一個介面轉換成客戶希望的另一個介面,使介面不相容的那些類可以一起工作,其別名為包裝器(Wrapper)。適配器模式既可以作為類結構型模式,也可以作為對象結構型模式。
優點:
①可以在不修改原有代碼的基礎上來複用現有類,很好地符合 “開閉原則”(這點是兩種實現方式都具有的)
②採用 “對象組合”的方式,更符合松耦合。
缺點:
①使得重定義Adaptee的行為較困難,這就需要生成Adaptee的子類並且使得Adapter引用這個子類而不是引用Adaptee本身。
適用場景:
①系統需要復用現有類,而該類的介面不符合系統的需求
②想要建立一個可重覆使用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作。
③對於對象適配器模式,在設計里需要改變多個已有子類的介面,如果使用類的適配器模式,就要針對每一個子類做一個適配器,而這不太實際。
橋接模式
將抽象部分與它的實現部分分離,使它們都可以獨立地變化。它是一種對象結構型模式,又稱為柄體(Handle and Body)模式或介面(Interface)模式。
優點:
①把抽象介面與其實現解耦。
②抽象和實現可以獨立擴展,不會影響到對方。
③實現細節對客戶透明,對用於隱藏了具體實現細節。
缺點:
增加了系統的複雜度
使用場景:
①如果一個系統需要在構件的抽象化角色和具體化角色之間添加更多的靈活性,避免在兩個層次之間建立靜態的聯繫。
②設計要求實現化角色的任何改變不應當影響客戶端,或者實現化角色的改變對客戶端是完全透明的。
③需要跨越多個平臺的圖形和視窗系統上。
④一個類存在兩個獨立變化的維度,且兩個維度都需要進行擴展。
組合模式
組合多個對象形成樹形結構以表示具有“整體—部分”關係的層次結構。組合模式對單個對象(即葉子對象)和組合對象(即容器對象)的使用具有一致性,組合模式又可以稱為“整體—部分”(Part-Whole)模式,它是一種對象結構型模式。
優點:
①組合模式使得客戶端代碼可以一致地處理對象和對象容器,無需關係處理的單個對象,還是組合的對象容器。
②將”客戶代碼與複雜的對象容器結構“解耦。
③可以更容易地往組合對象中加入新的構件。
缺點:
使得設計更加複雜。客戶端需要花更多時間理清類之間的層次關係。(這個是幾乎所有設計模式所面臨的問題)。
在以下情況下應該考慮使用組合模式:
①需要表示一個對象整體或部分的層次結構。
②希望用戶忽略組合對象與單個對象的不同,用戶將統一地使用組合結構中的所有對象。
裝飾模式
動態地給一個對象增加一些額外的職責,就增加對象功能來說,裝飾模式比生成子類實現更為靈活。裝飾模式是一種對象結構型模式。
優點:
①裝飾這模式和繼承的目的都是擴展對象的功能,但裝飾者模式比繼承更靈活
②通過使用不同的具體裝飾類以及這些類的排列組合,設計師可以創造出很多不同行為的組合
③裝飾者模式有很好地可擴展性
缺點:
①裝飾者模式會導致設計中出現許多小對象,如果過度使用,會讓程式變的更複雜。並且更多的對象會是的差錯變得困難,特別是這些對象看上去都很像。
使用場景:
①需要擴展一個類的功能或給一個類增加附加責任。
②需要動態地給一個對象增加功能,這些功能可以再動態地撤銷。
③需要增加由一些基本功能的排列組合而產生的非常大量的功能
外觀模式
為子系統中的一組介面提供一個統一的入口。外觀模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。
優點:
①外觀模式對客戶屏蔽了子系統組件,從而簡化了介面,減少了客戶處理的對象數目並使子系統的使用更加簡單。
②外觀模式實現了子系統與客戶之間的松耦合關係,而子系統內部的功能組件是緊耦合的。松耦合使得子系統的組件變化不會影響到它的客戶。
缺點:
①如果增加新的子系統可能需要修改外觀類或客戶端的源代碼,這樣就違背了”開——閉原則“(不過這點也是不可避免)。
使用場景:
①外一個複雜的子系統提供一個簡單的介面
②提供子系統的獨立性
③在層次化結構中,可以使用外觀模式定義系統中每一層的入口。其中三層架構就是這樣的一個例子。
享元模式
運用共用技術有效的支持大量細粒度的對象。
享元模式優點就在於它能夠大幅度的降低記憶體中對象的數量;而為了做到這一步也帶來了它的缺點:它使得系統邏輯複雜化,而且在一定程度上外蘊狀態影響了系統的速度。
使用場景:
①一個系統中有大量的對象,這些對象耗費大量的記憶體,這些對象中的狀態大部分都可以被外部化。
②這些對象可以按照內部狀態分成很多的組,當把外部對象從對象中剔除時,每一個組都可以僅用一個對象代替
③軟體系統不依賴這些對象的身份,
代理模式
給某一個對象提供一個代理或占位符,並由代理對象來控制對原對象的訪問。
優點:
①代理模式能夠將調用用於真正被調用的對象隔離,在一定程度上降低了系統的耦合度;
②代理對象在客戶端和目標對象之間起到一個中介的作用,這樣可以起到對目標對象的保護。代理對象可以在對目標對象發出請求之前進行一個額外的操作,例如許可權檢查等。
缺點:
①由於在客戶端和真實主題之間增加了一個代理對象,所以會造成請求的處理速度變慢
②實現代理類也需要額外的工作,從而增加了系統的實現複雜度。
使用場景:
①遠程代理,也就是為一個對象在不同的地址空間提供局部代表。這樣可以隱藏一個對象存在於不同地址空間的事實。
②虛擬代理,是根據需要創建開銷很大的對象。通過它來存放實例化需要很長世間的真實對象。
③安全代理,用來控制真是對象訪問時的許可權。
④智能指引,是指當調用真實的對象時,代理處理另外一些事。