十種經常使用的設計模式

 

1.       單例模式:html

實現方式:算法

a) 將被實現的類的構造方法設計成private的。數據庫

b) 添加此類引用的靜態成員變量,併爲其實例化。windows

c)  在被實現的類中提供公共的CreateInstance函數,返回實例化的此類,就是b中的靜態成員變量。安全

 

應用場景:多線程

優勢: 
    1.在單例模式中,活動的單例只有一個實例,對單例類的全部實例化獲得的都是相同的一個實例。這樣就 防止其它對象對本身的實例化,確保全部的對象都訪問一個實例 
    2.單例模式具備必定的伸縮性,類本身來控制實例化進程,類就在改變實例化進程上有相應的伸縮性。 
    3.提供了對惟一實例的受控訪問。 
    4.因爲在系統內存中只存在一個對象,所以能夠 節約系統資源,當 須要頻繁建立和銷燬的對象時單例模式無疑能夠提升系統的性能。 
    5.容許可變數目的實例。 
    6.避免對共享資源的多重佔用。 
缺點: 
    1.不適用於變化的對象,若是同一類型的對象老是要在不一樣的用例場景發生變化,單例就會引發數據的錯誤,不能保存彼此的狀態。 
    2.因爲單利模式中沒有抽象層,所以單例類的擴展有很大的困難。 
    3.單例類的職責太重,在必定程度上違背了「單一職責原則」。 
    4.濫用單例將帶來一些負面問題,如爲了節省資源將數據庫鏈接池對象設計爲的單例類,可能會致使共享鏈接池對象的程序過多而出現鏈接池溢出;若是實例化的對象長時間不被利用,系統會認爲是垃圾而被回收,這將致使對象狀態的丟失。 
使用注意事項: 
    1.使用時不能用反射模式建立單例,不然會實例化一個新的對象 
    2.使用懶單例模式時注意線程安全問題 
    3.單例模式和懶單例模式構造方法都是私有的,於是是不能被繼承的,有些單例模式能夠被繼承(如登記式模式) 
適用場景: 
    單例模式只容許建立一個對象,所以節省內存,加快對象訪問速度,所以對象須要被公用的場合適合使用,如多個模塊使用同一個數據源鏈接對象等等。如: 
    1.須要頻繁實例化而後銷燬的對象。 
    2.建立對象時耗時過多或者耗資源過多,但又常常用到的對象。 
    3.有狀態的工具類對象。 
    4.頻繁訪問數據庫或文件的對象。 
如下都是單例模式的經典使用場景: 
    1.資源共享的狀況下,避免因爲資源操做時致使的性能或損耗等。如上述中的日誌文件,應用配置。 
    2.控制資源的狀況下,方便資源之間的互相通訊。如線程池等。 
應用場景舉例: 
    1.外部資源:每臺計算機有若干個打印機,但只能有一個PrinterSpooler,以免兩個打印做業同時輸出到打印機。內部資源:大多數軟件都有一個(或多個)屬性文件存放系統配置,這樣的系統應該有一個對象管理這些屬性文件 
    2. Windows的TaskManager(任務管理器)就是很典型的單例模式(這個很熟悉吧),想一想看,是否是呢,你能打開兩個windows task manager嗎? 不信你本身試試看哦~ 
    3. windows的Recycle Bin(回收站)也是典型的單例應用。在整個系統運行過程當中,回收站一直維護着僅有的一個實例。 
    4. 網站的計數器,通常也是採用單例模式實現,不然難以同步。 
    5. 應用程序的日誌應用,通常都何用單例模式實現,這通常是因爲共享的日誌文件一直處於打開狀態,由於只能有一個實例去操做,不然內容很差追加。 
    6. Web應用的配置對象的讀取,通常也應用單例模式,這個是因爲配置文件是共享的資源。 
    7. 數據庫鏈接池的設計通常也是採用單例模式,由於數據庫鏈接是一種數據庫資源。數據庫軟件系統中使用數據庫鏈接池,主要是節省打開或者關閉數據庫鏈接所引發的效率損耗,這種效率上的損耗仍是很是昂貴的,由於何用單例模式來維護,就能夠大大下降這種損耗。 
    8. 多線程的線程池的設計通常也是採用單例模式,這是因爲線程池要方便對池中的線程進行控制。 
    9. 操做系統的文件系統,也是大的單例模式實現的具體例子,一個操做系統只能有一個文件系統。 
    10. HttpApplication 也是單位例的典型應用。熟悉ASP.Net(IIS)的整個請求生命週期的人應該知道HttpApplication也是單例模式,全部的HttpModule都共享一個HttpApplication實例. 函數

 

 

2.       策略模式:工具

實現方式:post

a)      提供公共接口或抽象類,定義須要使用的策略方法。(策略抽象類)性能

b)      多個實現的策略抽象類的實現類。(策略實現類)

c)       環境類,對多個實現類的封裝,提供接口類型的成員量,能夠在客戶端中切換。

d)      客戶端 調用環境類 進行不一樣策略的切換。

注:Jdk中的TreeSet和 TreeMap的排序功能就是使用了策略模式。

 

策略模式的優勢

  (1)策略模式提供了管理相關的算法族的辦法。策略類的等級結構定義了一個算法或行爲族。恰當使用繼承能夠把公共的代碼移到父類裏面,從而避免代碼重複。

  (2)使用策略模式能夠避免使用多重條件(if-else)語句。多重條件語句不易維護,它把採起哪種算法或採起哪種行爲的邏輯與算法或行爲的邏輯混合在一塊兒,通通列在一個多重條件語句裏面,比使用繼承的辦法還要原始和落後。

策略模式的缺點

  (1)客戶端必須知道全部的策略類,並自行決定使用哪個策略類。這就意味着客戶端必須理解這些算法的區別,以便適時選擇恰當的算法類。換言之,策略模式只適用於客戶端知道算法或行爲的狀況。

  (2)因爲策略模式把每一個具體的策略實現都單獨封裝成爲類,若是備選的策略不少的話,那麼對象的數目就會很可觀。

 

3.       代理模式:
一)靜態代理

實現方式:

a) 爲真實類和代理類提供的公共接口或抽象類。(租房)

b) 真實類,具體實現邏輯,實現或繼承a。(房主向外租房)

c)  代理類,實現或繼承a,有對b的引用,調用真實類的具體實現。(中介)

d) 客戶端,調用代理類實現對真實類的調用。(租客租房)

二)動態代理

實現方式:

a) 公共的接口(必須是接口,由於Proxy類的newproxyinstance方法的第二參數必須是個接口類型的Class)

b) 多個真實類,具體實現的業務邏輯。

c)  代理類,實現InvocationHandler接口,提供Object成員變量,和Set方法,便於客戶端切換。

d) 客戶端,得到代理類的實例,爲object實例賦值,調用Proxy.newproxyinstance方法在程序運行時生成繼承公共接口的實例,調用相應方法,此時方法的執行由代理類實現的Invoke方法接管。

 

jdk動態代理使用的侷限性:
經過反射類ProxyInvocationHandler回調接口實現的jdk動態代理,要求委託類必須實現一個接口,但事實上並非全部類都有接口,對於沒有實現接口的類,便沒法使用該方方式實現動態代理。

 

4.       觀察者模式:

觀察者模式是對象的行爲模式,又叫發佈-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式。

實現方式:

a) 角色抽象類(提供對觀察者的添加,刪除和通知功能)。

b) 角色具體類,實現a,維護一個c的集合(對角色抽象類的實現)。

c)  觀察者抽象類(被角色通知後實現的方法)。

d) 觀察者實現類,實現c(多個)。

注:JDK提供了對觀察者模式的支持,使用Observable類和Observer接口

 

兩種模型(推模型和拉模型):

■  推模型是假定主題對象知道觀察者須要的數據;而拉模型是主題對象不知道觀察者具體須要什麼數據,沒有辦法的狀況下,乾脆把自身傳遞給觀察者,讓觀察者本身去按須要取值。

■  推模型可能會使得觀察者對象難以複用,由於觀察者的update()方法是按須要定義的參數,可能沒法兼顧沒有考慮到的使用狀況。這就意味着出現新狀況的時候,就可能提供新的update()方法,或者是乾脆從新實現觀察者;而拉模型就不會形成這樣的狀況,由於拉模型下,update()方法的參數是主題對象自己,這基本上是主題對象能傳遞的最大數據集合了,基本上能夠適應各類狀況的須要。

  

 

5.       裝飾模式:

實現方式:

a)       抽象的被裝飾角色 (全部的角色都要直接或間接的實現本角色)

b)       具體的被裝飾角色,實現或繼承a (被功能擴展的角色)

c)       裝飾角色,實現或繼承a (本類有對a的引用,全部的具體裝飾角色都須要繼承這個角色)

d)       多個具體修飾角色 ,繼承c(對被裝飾角色的功能擴展,能夠任意搭配使用)

 

意圖: 

動態地給一個對象添加一些額外的職責。就增長功能來講,Decorator模式相比生成子類更爲靈活。該模式以對客 戶端透明的方式擴展對象的功能。

適用環境:

(1)在不影響其餘對象的狀況下,以動態、透明的方式給單個對象添加職責。

(2)處理那些能夠撤消的職責。

(3)當不能採用生成子類的方法進行擴充時。一種狀況是,可能有大量獨立的擴展,爲支持每一種組合將產生大量的 子類,使得子類數目呈爆炸性增加。另外一種狀況多是由於類定義被隱藏,或類定義不能用於生成子類。

  

6.      適配器模式:

適配器模式把一個類的接口變換成客戶端所期待的另外一種接口,從而使本來因接口不匹配而沒法在一塊兒工做的兩個類可以在一塊兒工做。

1.       類適配器(子類繼承方式)

實現方式:

a)     目標抽象角色(定義客戶要用的接口)

b)     適配器(實現a繼承c,做爲一個轉換器被客戶調用)

c)     待適配器(真正須要被調用的)

d)     客戶端(借用a的實例調用c的方法)

 

2.     對象適配器(對象的組合方式)

實現方式:

a)     目標抽象角色(定義客戶要用的接口)

b)     適配器(實現a,維護一個c的引用,做爲一個轉換器被d調用)

c)     待適配器(真正須要被調用的)

d)     客戶端(此類,借用a類的實例調用c類的方法,相似靜態代理,可是解決的問題不一樣)

 

3.     缺省的方式

實現方式:

a)     抽象接口

b)     實現a的適配器類(空實現)

c)     客戶端,繼承b,調用b中的方法,沒必要直接實現a(直接實現a須要實現a中的全部的方法)

適配器模式的優勢:

1.     更好的複用性

  系統須要使用現有的類,而此類的接口不符合系統的須要。那麼經過適配器模式就可讓這些功能獲得更好的複用。

2.     更好的擴展性

在實現適配器功能的時候,能夠調用本身開發的功能,從而天然地擴展系統的功能。

適配器模式的缺點:

  過多的使用適配器,會讓系統很是零亂,不易總體進行把握。好比,明明看到調用的是A接口,其實內部被適配成了B接口的實現,一個系統若是太多出現這種狀況,無異於一場災難。所以若是不是頗有必要,能夠不使用適配器,而是直接對系統進行重構。

 

 

7.    命令模式

將一個請求封裝爲一個對象,從而可用不一樣的請求對客戶進行參數化;對請求排隊或記錄日誌,以及支持可撤銷的操做

將「發出請求的對象」和」接收與執行這些請求的對象」分隔開來。

實現方式:

a)     抽象的命令角色 , 如:菜單(規定能夠點哪些菜)

b)     具體的命令角色(實現a 維護一個對c的引用),如:訂單(已點的菜)

c)     接收者(具體執行命令的角色),實際操做時,很常見使用"聰明"命令對象,也就是直接實現了請求,而不是將工做委託給c (弊端?) 如:廚師接收訂單後作菜

d)     調用者(維護一個對a的引用),如:服務員負責點菜並把訂單推給廚師

e)     客戶端 調用d發出命令進而執行c的方法,如:顧客點餐

 

效果:
1)、command模式將調用操做的對象和實現該操做的對象解耦
2)、能夠將多個命令裝配成一個複合命令,複合命令是Composite模式的一個實例
3)、增長新的command很容易,無需改變已有的類
適用性:
1)、抽象出待執行的動做以參數化某對象
2)、在不一樣的時刻指定、排列和執行請求。如請求隊列
3)、支持取消操做
4)、支持修改日誌
5)、用構建在原語操做上的高層操做構造一個系統。支持事物

 

8.    組合模式

將對象組合成樹形結構以表示「部分總體」的層次結構。組合模式使得用戶對單個對象和複雜對象的使用具備一致性。

實現方式:

a)     抽象的構件接口 (規範執行的方法),b及c都需實現此接口,如:Junit中的Test接口

b)     葉部件(實現a,最小的執行單位),如:Junit中咱們所編寫的測試用例

c)     組合類(實現a並維護一個a的集合[多個b的組合]),如:Junit中的 TestSuite

d)     客戶端 能夠隨意的將b和c進行組合,進行調用

 

 

什麼狀況下使用組合模式:

當發現需求中是體現部分與總體層次結構時,以及你但願用戶能夠忽略組合對象與單個對象的不一樣,統一地使用組合結構中的全部對象時,就應該考慮組合模式了。

 

 

 

 

 

 

9.    簡單工廠模式

就是創建一個工廠類,對實現了同一接口的一些類進行實例的建立。簡單工廠模式的實質是由一個工廠類根據傳入的參數,動態決定應該建立哪個產品類(這些產品類繼承自一個父類或接口)的實例。

實現方式:

a)     抽象產品類(也能夠是接口)

b)     多個具體的產品類

c)     工廠類(包括建立a的實例的方法)

 

 

優勢:

工廠類是整個模式的關鍵.包含了必要的邏輯判斷,根據外界給定的信息,決定究竟應該建立哪一個具體類的對象.經過使用工廠類,外界能夠從直接建立具體產品對象的尷尬局面擺脫出來,僅僅須要負責「消費」對象就能夠了。而沒必要管這些對象究竟如何建立及如何組織的.明確了各自的職責和權利,有利於整個軟件體系結構的優化。

   

缺點:

因爲工廠類集中了全部實例的建立邏輯,違反了高內聚責任分配原則,將所有建立邏輯集中到了一個工廠類中;它所能建立的類只能是事先考慮到的,若是須要添加新的類,則就須要改變工廠類了。當系統中的具體產品類不斷增多時候,可能會出現要求工廠類根據不一樣條件建立不一樣實例的需求.這種對條件的判斷和對具體產品類型的判斷交錯在一塊兒,很難避免模塊功能的蔓延,對系統的維護和擴展很是不利;

 

  

10. 模板方法模式

實現方式:

a)     父類模板類(規定要執行的方法和順序,只關心方法的定義及順序,不關心方法實現)

b)     子類實現類(實現a規定要執行的方法,只關心方法實現,不關心調用順序)

 

 優勢:

        1)封裝不變部分,擴展可變部分:把認爲不變部分的算法封裝到父類實現,可變部分則能夠經過繼承來實現,很容易擴展。

        2)提取公共部分代碼,便於維護。

       3)行爲由父類控制,由子類實現。

 缺點:

        模板方法模式顛倒了咱們日常的設計習慣:抽象類負責聲明最抽象、最通常的事物屬性和方法,實現類實現具體的事物屬性和方法。在複雜的項目中可能會帶來代碼閱讀的難度。

相關文章
相關標籤/搜索