設計模式最全總結

                                  設計模式最全總結

 

什麼是設計模式 

設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的,設計模式使代碼編制真正工程化,設計模式是軟件工程的基石,如同大廈的一塊塊磚石一樣。項目中合理的運用設計模式可以完美的解決很多問題,每種模式在現在中都有相應的原理來與之對應,每一個模式描述了一個在我們周圍不斷重複發生的問題,以及該問題的核心解決方案,這也是它能被廣泛應用的原因。簡單說:

模式:在某些場景下,針對某類問題的某種通用的解決方案。

場景:項目所在的環境

問題:約束條件,項目目標等

解決方案:通用、可複用的設計,解決約束達到目標。

設計模式的三個分類  

創建型模式:對象實例化的模式,創建型模式用於解耦對象的實例化過程。

結構型模式:把類或對象結合在一起形成一個更大的結構。

行爲型模式:類和對象如何交互,及劃分責任和算法。

三、各分類中模式的關鍵點              

創建型

1 單例模式:某個類只能有一個實例,提供一個全局的訪問點。

實例: CSTK場景   數據庫連接池   多線程的線程池  Windows任務管理器 Spring中的Bean

Windows 是多進程多線程的,在操作一個文件的時候,就不可避免地出現多個進程或線程同時操作一個文件的現象,所以所有文件的處理必須通過唯一的實例來進行。

一些設備管理器常常設計爲單例模式,比如一個電腦有兩臺打印機,在輸出的時候就要處理不能兩臺打印機打印同一個文件。

2 簡單工廠:一個工廠類根據傳入的參量決定創建出那一種產品類的實例。

實例:BeanFactory

3 工廠方法:定義一個創建對象的接口,讓子類決定實例化那個類。

4 抽象工廠:創建相關或依賴對象的家族,而無需明確指定具體類。

5 建造者模式:封裝一個複雜對象的構建過程,並可以按步驟構造。

實例:去肯德基,漢堡、可樂、薯條、炸雞翅等是不變的,而其組合是經常變化的,生成出所謂的"套餐"。 

6 原型模式:通過複製現有的實例來創建新的實例。

實例:Object中的clone()方法,是native方法,直接操作內存中二進制流。

 結構型

7 適配器模式:將一個類的方法接口轉換成客戶希望的另外一個接口。

實例:使用double類型數組來表示六根數的參數,又有六根數類,就可以用適配器方法,將double數組轉換爲六根數。

1、美國電器 110V,中國 220V,就要有一個適配器將 110V 轉化爲 220V。

2、JAVA JDK 1.1 提供了 Enumeration 接口,而在 1.2 中提供了 Iterator 接口,想要使用 1.2 的 JDK,則要將以前系統的 Enumeration 接口轉化爲 Iterator 接口,這時就需要適配器模式。

3、在 LINUX 上運行 WINDOWS 程序。

4、JAVA 中的 jdbc。

8 組合模式:將對象組合成樹形結構以表示“”部分-整體“”的層次結構。

實例:部分、整體場景,如樹形菜單,文件、文件夾的管理。

組合模式則是將若干部分組合爲整體。

9 裝飾模式:動態的給對象添加新的功能。

實例:裝飾注重的是在原有功能的基礎上添加新的功能

IO流

流按操作數據分爲兩種:字節流與字符流.

流按流向分爲:輸入流(讀),輸出流(寫)。

字符流由來就是:早期的字節流+編碼表,爲了更便於操作文字數據。 

記住:只要是操作字符數據,應該優先使用字符流。

10 代理模式:爲其他對象提供一個代理以便控制這個對象的訪問。

實例:廠商產書,賣家進購後打折等等。  CGLIB和JDK代理 ????

Windows 裏面的快捷方式。

 買火車票不一定在火車站買,也可以去代售點。

11 亨元模式:通過共享技術來有效的支持大量細粒度的對象。

它使用共享技術對相同或者相似對象實現重用。享元模式就是運行共享技術有效地支持大量細粒度對象的複用。  String常量池 Integer等包裝類的緩存策略    數據庫的數據池。

12 外觀模式:對外提供一個統一的方法,來訪問子系統中的一羣接口。

客戶通過這個屏障來與子系統進行通信。通過使用外觀模式,使得客戶對子系統的引用變得簡單了,實現了客戶與子系統之間的鬆耦合。但是它違背了“開閉原則”,

13橋接模式:將抽象部分和它的實現部分分離,使它們都可以獨立的變化。

 實例:如覆蓋計算問題,覆蓋計算類可以作爲這個Abstraction,然後,網格點法,經度條帶法等作爲Abstraction的子類。然後,覆蓋計算問題(瞬時覆蓋,累積覆蓋等)可以被抽象爲Implementor,不同的覆蓋問題對應不同的子類。

主要解決:在有多種可能會變化的情況下,用繼承會造成類爆炸問題,擴展起來不靈活。

行爲型

14模板模式:定義一個算法結構,而將一些步驟延遲到子類實現。

實例:spring 中對 Hibernate 的支持,將一些已經定好的方法封裝起來,比如開啓事務、獲取 Session、關閉 Session 等,程序員不重複寫那些已經規範好的代碼,直接丟一個實體就可以保存。

模板是一種典型的基於繼承的多態。

在造房子的時候,地基、走線、水管都一樣,只有在建築的後期纔有加壁櫥加柵欄等差異。

15解釋器模式:給定一個語言,定義它的文法的一種表示,並定義一個解釋器。

實例:如對XML的解釋器等。 編譯器、運算表達式計算。

16策略模式:定義一系列算法,把他們封裝起來,並且使它們可以相互替換。

雖然策略模式定義了算法,但是它並不提供算法的選擇,即什麼算法對於什麼問題最合適這是策略模式所不關心的,所以對於策略的選擇還是要客戶端來做。客戶必須要清楚的知道每個算法之間的區別和在什麼時候什麼地方使用什麼策略是最合適的,這樣就增加客戶端的負擔。

17狀態模式:允許一個對象在其對象內部狀態改變時改變它的行爲。

我們對象的行爲依賴於它的一個或者多個變化的屬性,這些可變的屬性我們稱之爲狀態,也就是說行爲依賴狀態,即當該對象因爲在外部的互動而導致他的狀態發生變化,從而它的行爲也會做出相應的變化。對於這種情況,我們是不能用行爲來控制狀態的變化,而應該站在狀態的角度來思考行爲,即是什麼狀態就要做出什麼樣的行爲。

在狀態模式中我們可以減少大塊的if…else語句,它是允許態轉換邏輯與狀態對象合成一體,但是減少if…else語句的代價就是會換來大量的類,所以狀態模式勢必會增加系統中類或者對象的個數。

18觀察者模式:對象間的一對多的依賴關係。

實例:Unity3D仿真部分   發佈訂閱

19備忘錄模式:在不破壞封裝的前提下,保持對象的內部狀態。

實例:Windows 裏的 ctri + z。  IE 中的後退。

備忘錄模式就是在不破壞封裝性的前提下,捕獲並保存一個類的內部狀態,這樣就可以利用該狀態實施恢復操作。

20中介者模式:用一箇中介對象來封裝一系列的對象交互。

實例:MVC 框架,其中C(控制器)就是 M(模型)和 V(視圖)的中介者。     機場調度系統。

在中介者模式中,各個對象不需要互相知道了解,他們只需要知道中介者對象即可,但是中介者對象就必須要知道所有的對象和他們之間的關聯關係,正是因爲這樣就導致了中介者對象的結構過於複雜,承擔了過多的職責,同時它也是整個系統的核心所在,它有問題將會導致整個系統的問題。所以如果在系統的設計過程中如果出現“多對多”的複雜關係羣時,千萬別急着使用中介者模式,而是要仔細思考是不是您設計的系統存在問題。

21命令模式:將命令請求封裝爲一個對象,使得可以用不同的請求來進行參數化。

 實例:在某些場合,比如要對行爲進行"記錄、撤銷/重做、事務"等處理,這種無法抵禦變化的緊耦合是不合適的。在這種情況下,如何將"行爲請求者"與"行爲實現者"解耦?將一組行爲抽象爲對象,可以實現二者之間的鬆耦合。

在面向對象的程序設計中,一個對象調用另一個對象般情況下的調用過程是:創建目標對象實例;設置調用參數;調用目標對象的方法。但在有些情況下有必要使用一個專門的類對這種調用過程加以封裝,我們把這種專門的類稱作 command類整個調用過程比較繁雜,或者存在多處這種調用這時,使用 Command類對該調用加以封裝,便於功能的再利用。

1 調用前後需要對調用參數進行某些處理。

2 調用前後需要進行某些額外處理,比如日誌,緩存,記錄歷史操作等。

22訪問者模式:在不改變數據結構的前提下,增加作用於一組對象元素的新功能。

 

23責任鏈模式:將請求的發送者和接收者解耦,使的多個對象都有處理這個請求的機會。

它將對象組成一條鏈,發送者將請求發給鏈的第一個接收者,並且沿着這條鏈傳遞,直到有一個對象來處理它或者直到最後也沒有對象處理而留在鏈末尾端。

24迭代器模式:一種遍歷訪問聚合對象中各個元素的方法,不暴露該對象的內部結構。

Iterable

根據不同的需求以不同的方式來遍歷整個對象,但是我們又不希望在聚合對象的抽象接口中充斥着各種不同的遍歷操作,於是我們就希望有某個東西能夠以多種不同的方式來遍歷一個聚合對象,這時迭代器模式出現了。

 

https://www.jianshu.com/p/4a5a0a92e7d5

 

  1. 單例模式   (完成) 

單例模式,它的定義就是確保某一個類只有一個實例,並且提供一個全局訪問點。

單例模式具備典型的3個特點:1、只有一個實例。 2、自我實例化。 3、提供全局訪問點。

因此當系統中只需要一個實例對象或者系統中只允許一個公共訪問點,除了這個公共訪問點外,不能通過其他訪問點訪問該實例時,可以使用單例模式。

單例模式的主要優點就是節約系統資源、提高了系統效率,同時也能夠嚴格控制客戶對它的訪問。也許就是因爲系統中只有一個實例,這樣就導致了單例類的職責過重,違背了單一職責原則,同時也沒有抽象類,所以擴展起來有一定的困難。其UML結構圖非常簡單,就只有一個類,如下圖:

優點: 1、在內存裏只有一個實例,減少了內存的開銷,尤其是頻繁的創建和銷燬實例(比如管理學院首頁頁面緩存)。 2、避免對資源的多重佔用(比如寫文件操作)。

缺點:沒有接口,不能繼承,與單一職責原則衝突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來實例化。

使用場景 1、要求生產唯一序列號。 2WEB 中的計數器,不用每次刷新都在數據庫里加一次,用單例先緩存起來。 3、創建的一個對象需要消耗的資源過多,比如 I/O 與數據庫的連接等。

Java應用程序訪問數據庫的基本原理

  在Java語言中,JDBC(Java DataBase Connection)是應用程序與數據庫溝通的橋樑,

  即Java語言通過JDBC技術訪問數據庫。JDBC是一種“開放”的方案,它爲數據庫應用開發人員﹑數據庫前臺工具開發人員提供了一種標準的應用程序設計接口,使開發人員可以用純Java語言編寫完整的數據庫應用程序。JDBC提供兩種API,分別是面向開發人員的API和麪向底層的JDBC驅動程序API,底層主要通過直接的JDBC驅動和JDBC-ODBC橋驅動實現與數據庫的連接。

  一般來說,Java應用程序訪問數據庫的過程(如圖1所示)是:

  ①裝載數據庫驅動程序;

  ②通過JDBC建立數據庫連接;

  ③訪問數據庫,執行SQL語句;

  ④斷開數據庫連接。

 1、連接池模型

  本文討論的連接池包括一個連接池類(DBConnectionPool)一個連接池管理類(DBConnetionPoolManager)。連接池類是對某一數據庫所有連接的“緩衝池”,主要實現以下功能:①從連接池獲取或創建可用連接;②使用完畢之後,把連接返還給連接池;③在系統關閉前,斷開所有連接並釋放連接佔用的系統資源;④還能夠處理無效連接(原來登記爲可用的連接,由於某種原因不再可用,如超時,通訊問題),並能夠限制連接池中的連接總數不低於某個預定值和不超過某個預定值。

  連接池管理類是連接池類的外覆類(wrapper),符合單例模式,即系統中只能有一個連接池管理類的實例。其主要用於對多個連接池對象的管理,具有以下功能:①裝載並註冊特定數據庫的JDBC驅動程序;②根據屬性文件給定的信息,創建連接池對象;③爲方便管理多個連接池對象,爲每一個連接池對象取一個名字,實現連接池名字與其實例之間的映射;④跟蹤客戶使用連接情況,以便需要是關閉連接釋放資源。連接池管理類的引入主要是爲了方便對多個連接池的使用和管理,如系統需要連接不同的數據庫,或連接相同的數據庫但由於安全性問題,需要不同的用戶使用不同的名稱和密碼。

  1. 工廠方法模式(完成)

工廠模式與簡單工廠不一樣的地方是把實際的創建工作推遲到子類當中。核心類成爲一個創建產品對象的工廠接口。

 

 

作爲抽象工廠模式的孿生兄弟,工廠方法模式定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個,也就是說工廠方法模式讓實例化推遲到子類。

 

工廠方法模式非常符合“開閉原則”,當需要增加一個新的產品時,我們只需要增加一個具體的產品類和與之對應的具體工廠即可,無須修改原有系統。同時在工廠方法模式中用戶只需要知道生產產品的具體工廠即可,無須關係產品的創建過程,甚至連具體的產品類名稱都不需要知道。雖然他很好的符合了“開閉原則”,但是由於每新增一個新產品時就需要增加兩個類,這樣勢必會導致系統的複雜度增加。

抽象工廠模式(完成)

抽象工廠模式 對產品又進行了抽象 就拿蘋果來說,不只是蘋果。還分溫室的,南方的,北方的。

 

 

所謂抽象工廠模式就是提供一個接口,用於創建相關或者依賴對象的家族,而不需要明確指定具體類。他允許客戶端使用抽象的接口來創建一組相關的產品,而不需要關係實際產出的具體產品是什麼。這樣一來,客戶就可以從具體的產品中被解耦。它的優點是隔離了具體類的生成,使得客戶端不需要知道什麼被創建了,而缺點就在於新增新的行爲會比較麻煩,因爲當添加一個新的產品對象時,需要更加需要更改接口及其下所有子類。

建造者模式(完成)

對於建造者模式而已,它主要是將一個複雜對象的構建與表示分離,使得同樣的構建過程可以創建不同的表示。適用於那些產品對象的內部結構比較複雜。

 

建造者模式將複雜產品的構建過程封裝分解在不同的方法中,使得創建過程非常清晰,能夠讓我們更加精確的控制複雜產品對象的創建過程,同時它隔離了複雜產品對象的創建和使用,使得相同的創建過程能夠創建不同的產品。但是如果某個產品的內部結構過於複雜,將會導致整個系統變得非常龐大,不利於控制,同時若幾個產品之間存在較大的差異,則不適用建造者模式,畢竟這個世界上存在相同點大的兩個產品並不是很多,所以它的使用範圍有限。其UML結構圖:優點: 1、建造者獨立,易擴展。 2、便於控制細節風險。

缺點: 1、產品必須有共同點,範圍有限制。 2、如內部變化複雜,會有很多的建造類。

使用場景: 1、需要生成的對象具有複雜的內部結構。 2、需要生成的對象內部屬性本身相互依賴。

注意事項:與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。

  1. 原型模式   (完成)

在我們應用程序可能有某些對象的結構比較複雜,但是我們又需要頻繁的使用它們,如果這個時候我們來不斷的新建這個對象勢必會大大損耗系統內存的,這個時候我們需要使用原型模式來對這個結構複雜又要頻繁使用的對象進行克隆。所以原型模式就是用原型實例指定創建對象的種類,並且通過複製這些原型創建新的對象。

它主要應用與那些創建新對象的成本過大時。它的主要優點就是簡化了新對象的創建過程,提高了效率,同時原型模式提供了簡化的創建結構

 

 

  

模式結構


原型模式包含如下角色:
Prototype:抽象原型類
ConcretePrototype:具體原型類
Client:客戶類

優點: 1、性能提高。 2、逃避構造函數的約束。

缺點: 1、配備克隆方法需要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不一定很容易,特別當一個類引用不支持串行化的間接對象,或者引用含有循環結構的時候。 2、必須實現 Cloneable 接口。

使用場景

1、資源優化場景。

2、類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等。

3、性能和安全要求的場景。

4、通過 new 產生一個對象需要非常繁瑣的數據準備或訪問權限,則可以使用原型模式。

5、一個對象多個修改者的場景。

6、一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調用者使用。

7、在實際項目中,原型模式很少單獨出現,一般是和工廠方法模式一起出現,通過 clone 的方法創建一個對象,然後由工廠方法提供給調用者。原型模式已經與 Java 融爲渾然一體,大家可以隨手拿來使用。

https://blog.csdn.net/weixin_41563161/article/details/101628243

https://blog.csdn.net/weixin_41563161/article/details/102941595

  1. 適配器模式(完成)

在我們的應用程序中我們可能需要將兩個不同接口的類來進行通信,在不修改這兩個的前提下我們可能會需要某個中間件來完成這個銜接的過程。這個中間件就是適配器。所謂適配器模式就是將一個類的接口,轉換成客戶期望的另一個接口。它可以讓原本兩個不兼容的接口能夠無縫完成對接。

作爲中間件的適配器將目標類和適配者解耦,增加了類的透明性和可複用性。

適配器模式包含如下角色:
Target:目標抽象類
Adapter:適配器類
Adaptee:適配者類
Client:客戶類

方法1(繼承的方式)

方法2

優點: 1、可以讓任何兩個沒有關聯的類一起運行。 2、提高了類的複用。 3、增加了類的透明度。 4、靈活性好。

缺點: 1、過多地使用適配器,會讓系統非常零亂,不易整體進行把握。比如,明明看到調用的是 A 接口,其實內部被適配成了 B 接口的實現,一個系統如果太多出現這種情況,無異於一場災難。因此如果不是很有必要,可以不使用適配器,而是直接對系統進行重構。 2.由於 JAVA 至多繼承一個類,所以至多隻能適配一個適配者類,而且目標類必須是抽象類。

使用場景:有動機地修改一個正常運行的系統的接口,這時應該考慮使用適配器模式。

  1. 橋接模式    (完成)

如果說某個系統能夠從多個角度來進行分類,且每一種分類都可能會變化,那麼我們需要做的就是講這多個角度分離出來,使得他們能獨立變化,減少他們之間的耦合,這個分離過程就使用了橋接模式。所謂橋接模式就是講抽象部分和實現部分隔離開來,使得他們能夠獨立變化。

 

橋接模式將繼承關係轉化成關聯關係,封裝了變化,完成了解耦,減少了系統中類的數量,也減少了代碼量。

橋接模式包含如下角色:
Abstraction:抽象類
RefinedAbstraction:擴充抽象類
Implementor:實現類接口
ConcreteImplementor:具體實現類

 

優點: 1、抽象和實現的分離。 2、優秀的擴展能力。 3、實現細節對客戶透明。

缺點:橋接模式的引入會增加系統的理解與設計難度,由於聚合關聯關係建立在抽象層,要求開發者針對抽象進行設計與編程。

使用場景: 1、如果一個系統需要在構件的抽象化角色和具體化角色之間增加更多的靈活性,避免在兩個層次之間建立靜態的繼承聯繫,通過橋接模式可以使它們在抽象層建立一個關聯關係。 2、對於那些不希望使用繼承或因爲多層次繼承導致系統類的個數急劇增加的系統,橋接模式尤爲適用。 3、一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴展。

注意事項:對於兩個獨立變化的維度,使用橋接模式再適合不過了。

 

  1. 組合模式    (完成)

組合模式組合多個對象形成樹形結構以表示整體-部分的結構層次。它定義瞭如何將容器對象和葉子對象進行遞歸組合,使得客戶在使用的過程中無須進行區分,可以對他們進行一致的處理。在使用組合模式中需要注意一點也是組合模式最關鍵的地方:葉子對象和組合對象實現相同的接口。這就是組合模式能夠將葉子節點和對象節點進行一致處理的原因。

 

雖然組合模式能夠清晰地定義分層次的複雜對象,也使得增加新構件也更容易,但是這樣就導致了系統的設計變得更加抽象,如果系統的業務規則比較複雜的話,使用組合模式就有一定的挑戰了。

模式結構
組合模式包含如下角色:
Component: 抽象構件
Leaf: 葉子構件
Composite: 容器構件
Client: 客戶類

優點: 1、高層模塊調用簡單。 2、節點自由增加。

缺點:在使用組合模式時,其葉子和樹枝的聲明都是實現類,而不是接口,違反了依賴倒置原則。

使用場景:部分、整體場景,如樹形菜單,文件、文件夾的管理。

注意事項:定義時爲具體類。

  1. 裝飾模式    (完成)

我們可以通過繼承和組合的方式來給一個對象添加行爲,雖然使用繼承能夠很好擁有父類的行爲,但是它存在幾個缺陷:一、對象之間的關係複雜的話,系統變得複雜不利於維護。二、容易產生“類爆炸”現象。三、是靜態的。在這裏我們可以通過使用裝飾者模式來解決這個問題。

裝飾者模式,動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更加有彈性的替代方案。雖然裝飾者模式能夠動態將責任附加到對象上,但是他會產生許多的細小對象,增加了系統的複雜度。

模式結構
裝飾模式包含如下角色:
Component: 抽象構件
ConcreteComponent: 具體構件
Decorator: 抽象裝飾類
ConcreteDecorator: 具體裝飾類

優點:裝飾類和被裝飾類可以獨立發展,不會相互耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動態擴展一個實現類的功能。

缺點:多層裝飾比較複雜。

使用場景: 1、擴展一個類的功能。 2、動態增加功能,動態撤銷。

10 外觀模式   (完成)

我們都知道類與類之間的耦合越低,那麼可複用性就越好,如果兩個類不必彼此通信,那麼就不要讓這兩個類發生直接的相互關係,如果需要調用裏面的方法,可以通過第三者來轉發調用。外觀模式非常好的詮釋了這段話。外觀模式提供了一個統一的接口,用來訪問子系統中的一羣接口。它讓一個應用程序中子系統間的相互依賴關係減少到了最少,它給子系統提供了一個簡單、單一的屏障,客戶通過這個屏障來與子系統進行通信。通過使用外觀模式,使得客戶對子系統的引用變得簡單了,實現了客戶與子系統之間的鬆耦合。但是它違背了開閉原則,因爲增加新的子系統可能需要修改外觀類或客戶端的源代碼。

 

外觀模式包含如下角色:
Facade: 外觀角色
SubSystem:子系統角色

優點: 1、減少系統相互依賴。 2、提高靈活性。 3、提高了安全性。

缺點:不符合開閉原則,如果要改東西很麻煩,繼承重寫都不合適。

使用場景: 1、爲複雜的模塊或子系統提供外界訪問的模塊。 2、子系統相對獨立。 3、預防低水平人員帶來的風險。

注意事項:在層次化結構中,可以使用外觀模式定義系統中每一層的入口。

  1. 亨元模式   (完成)

在一個系統中對象會使得內存佔用過多,特別是那些大量重複的對象,這就是對系統資源的極大浪費。享元模式對對象的重用提供了一種解決方案,它使用共享技術對相同或者相似對象實現重用。享元模式就是運行共享技術有效地支持大量細粒度對象的複用。系統使用少量對象,而且這些都比較相似,狀態變化小,可以實現對象的多次複用。這裏有一點要注意:享元模式要求能夠共享的對象必須是細粒度對象。享元模式通過共享技術使得系統中的對象個數大大減少了,同時享元模式使用了內部狀態和外部狀態,同時外部狀態相對獨立,不會影響到內部狀態,所以享元模式能夠使得享元對象在不同的環境下被共享。同時正是分爲了內部狀態和外部狀態,享元模式會使得系統變得更加複雜,同時也會導致讀取外部狀態所消耗的時間過長。

享元模式包含如下角色:
Flyweight: 抽象享元類
ConcreteFlyweight: 具體享元類
UnsharedConcreteFlyweight: 非共享具體享元類
FlyweightFactory: 享元工廠類

 

  

優點:大大減少對象的創建,降低系統的內存,使效率提高。

缺點:提高了系統的複雜度,需要分離出外部狀態和內部狀態,而且外部狀態具有固有化的性質,不應該隨着內部狀態的變化而變化,否則會造成系統的混亂。

使用場景: 1、系統有大量相似對象。 2、需要緩衝池的場景。

注意事項: 1、注意劃分外部狀態和內部狀態,否則可能會引起線程安全問題。 2、這些類必須有一個工廠對象加以控制。

12.代理模式   (完成)  

代理模式就是給一個對象提供一個代理,並由代理對象控制對原對象的引用它使得客戶不能直接與真正的目標對象通信。代理對象是目標對象的代表,其他需要與這個目標對象打交道的操作都是和這個代理對象在交涉。

代理對象可以在客戶端和目標對象之間起到中介的作用,這樣起到了的作用和保護了目標對象的,同時也在一定程度上面減少了系統的耦合度。

代理模式包含如下角色:
o Subject: 抽象主題角色
o Proxy: 代理主題角色
o RealSubject: 真實主題角色

 

優點: 1、職責清晰。 2、高擴展性。 3、智能化。

缺點: 1、由於在客戶端和真實主題之間增加了代理對象,因此有些類型的代理模式可能會造成請求的處理速度變慢。 2、實現代理模式需要額外的工作,有些代理模式的實現非常複雜。

使用場景:按職責來劃分,通常有以下使用場景: 1、遠程代理。 2、虛擬代理。 3、Copy-on-Write 代理。 4、保護(Protect or Access)代理。 5、Cache代理。 6、防火牆(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。

注意事項: 1、和適配器模式的區別:適配器模式主要改變所考慮對象的接口,而代理模式不能改變所代理類的接口。 2、和裝飾器模式的區別:裝飾器模式爲了增強功能,而代理模式是爲了加以控制。

 

13.訪問者模式(完成)

訪問者模式俗稱23大設計模式中最難的一個。除了結構複雜外,理解也比較難。在我們軟件開發中我們可能會對同一個對象有不同的處理,如果我們都做分別的處理,將會產生災難性的錯誤。對於這種問題,訪問者模式提供了比較好的解決方案。訪問者模式即表示一個作用於某對象結構中的各元素的操作,它使我們可以在不改變各元素的類的前提下定義作用於這些元素的新操作。

訪問者模式的目的是封裝一些施加於某種數據結構元素之上的操作,一旦這些操作需要修改的話,接受這個操作的數據結構可以保持不變。爲不同類型的元素提供多種訪問操作方式,且可以在不修改原有系統的情況下增加新的操作方式。同時我們還需要明確一點那就是訪問者模式是適用於那些數據結構比較穩定的,因爲他是將數據的操作與數據結構進行分離了,如果某個系統的數據結構相對穩定,但是操作算法易於變化的話,就比較適用適用訪問者模式,因爲訪問者模式使得算法操作的增加變得比較簡單了。

訪問者模式包含如下角色:
Vistor: 抽象訪問者
ConcreteVisitor: 具體訪問者
Element: 抽象元素
ConcreteElement: 具體元素 
ObjectStructure: 對象結構

優點: 1、符合單一職責原則。 2、優秀的擴展性。 3、靈活性。

缺點: 1、具體元素對訪問者公佈細節,違反了迪米特原則。 2、具體元素變更比較困難。 3、違反了依賴倒置原則,依賴了具體類,沒有依賴抽象。

使用場景: 1、對象結構中對象對應的類很少改變,但經常需要在此對象結構上定義新的操作。 2、需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而需要避免讓這些操作"污染"這些對象的類,也不希望在增加新操作時修改這些類。

注意事項:訪問者可以對功能進行統一,可以做報表、UI、攔截器與過濾器。

 

https://blog.csdn.net/weixin_41563161/article/details/106015391

14.模板模式   (完成)   

有些時候我們做某幾件事情的步驟都差不多,僅有那麼一小點的不同,在軟件開發的世界裏同樣如此,如果我們都將這些步驟都一一做的話,費時費力不討好。所以我們可以將這些步驟分解、封裝起來,然後利用繼承的方式來繼承即可,當然不同的可以自己重寫實現嘛!這就是模板方法模式提供的解決方案。

 

所謂模板方法模式就是在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些步驟。

 

模板方法模式就是基於繼承的代碼複用技術的。在模板方法模式中,我們可以將相同部分的代碼放在父類中,而將不同的代碼放入不同的子類中。也就是說我們需要聲明一個抽象的父類,將部分邏輯以具體方法以及具體構造函數的形式實現,然後聲明一些抽象方法讓子類來實現剩餘的邏輯,不同的子類可以以不同的方式來實現這些邏輯。所以模板方法的模板其實就是一個普通的方法,只不過這個方法是將算法實現的步驟封裝起來的。

模板方法模式包含如下角色:
AbstractClass: 抽象類 
ConcreteClass: 具體子類

 

優點: 1、封裝不變部分,擴展可變部分。 2、提取公共代碼,便於維護。 3、行爲由父類控制,子類實現。

缺點:每一個不同的實現都需要一個子類來實現,導致類的個數增加,使得系統更加龐大。

使用場景: 1、有多個子類共有的方法,且邏輯相同。 2、重要的、複雜的方法,可以考慮作爲模板方法。

注意事項:爲防止惡意操作,一般模板方法都加上 final 關鍵詞。

 

 

15 策略模式    (完成)

 我們知道一件事可能會有很多種方式來實現它,但是其中總有一種最高效的方式,在軟件開發的世界裏面同樣如此,我們也有很多中方法來實現一個功能,但是我們需要一種簡單、高效的方式來實現它,使得系統能夠非常靈活,這就是策略模式。

所以策略模式就是定義了算法族,分別封裝起來,讓他們之前可以互相轉換,此模式然該算法的變化獨立於使用算法的客戶。

在策略模式中它將這些解決問題的方法定義成一個算法羣,每一個方法都對應着一個具體的算法,這裏的一個算法我就稱之爲一個策略。雖然策略模式定義了算法,但是它並不提供算法的選擇,即什麼算法對於什麼問題最合適這是策略模式所不關心的,所以對於策略的選擇還是要客戶端來做。客戶必須要清楚的知道每個算法之間的區別和在什麼時候什麼地方使用什麼策略是最合適的,這樣就增加客戶端的負擔。

同時策略模式也非常完美的符合了開閉原則,用戶可以在不修改原有系統的基礎上選擇算法或行爲,也可以靈活地增加新的算法或行爲。但是一個策略對應一個類將會是系統產生很多的策略類。

 

策略模式包含如下角色:
Context: 環境類
Strategy: 抽象策略類
ConcreteStrategy: 具體策略類

 

優點: 1、算法可以自由切換。 2、避免使用多重條件判斷。 3、擴展性良好。

缺點: 1、策略類會增多。 2、所有策略類都需要對外暴露。

使用場景: 1、如果在一個系統裏面有許多類,它們之間的區別僅在於它們的行爲,那麼使用策略模式可以動態地讓一個對象在許多行爲中選擇一種行爲。 2、一個系統需要動態地在幾種算法中選擇一種。 3、如果一個對象有很多的行爲,如果不用恰當的模式,這些行爲就只好使用多重的條件選擇語句來實現。

注意事項:如果一個系統的策略多於四個,就需要考慮使用混合模式,解決策略類膨脹的問題。

策略模式:
定義了算法族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化獨立於使用算法的客戶。

裝飾者模式:
動態地將責任附加到對象上,若要擴展功能,裝飾者提供了比繼承更有彈性的代替方案。
eg:咖啡中加入各種調料;java.io包

16.狀態模式    (完成)

 在很多情況下我們對象的行爲依賴於它的一個或者多個變化的屬性,這些可變的屬性我們稱之爲狀態,也就是說行爲依賴狀態,即當該對象因爲在外部的互動而導致他的狀態發生變化,從而它的行爲也會做出相應的變化。對於這種情況,我們是不能用行爲來控制狀態的變化,而應該站在狀態的角度來思考行爲,即是什麼狀態就要做出什麼樣的行爲。這個就是狀態模式。

所以狀態模式就是允許對象在內部狀態發生改變時改變它的行爲,對象看起來好像修改了它的類。

在狀態模式中我們可以減少大塊的if…else語句,它是允許態轉換邏輯與狀態對象合成一體,但是減少if…else語句的代價就是會換來大量的類,所以狀態模式勢必會增加系統中類或者對象的個數。

同時狀態模式是將所有與某個狀態有關的行爲放到一個類中,並且可以方便地增加新的狀態,只需要改變對象狀態即可改變對象的行爲。但是這樣就會導致系統的結構和實現都會比較複雜,如果使用不當就會導致程序的結構和代碼混亂,不利於維護。

 

狀態模式包含如下角色:
Context: 環境類
State: 抽象狀態類
ConcreteState: 具體狀態類

優點: 1、封裝了轉換規則。 2、枚舉可能的狀態,在枚舉狀態之前需要確定狀態種類。 3、將所有與某個狀態有關的行爲放到一個類中,並且可以方便地增加新的狀態,只需要改變對象狀態即可改變對象的行爲。 4、允許狀態轉換邏輯與狀態對象合成一體,而不是某一個巨大的條件語句塊。 5、可以讓多個環境對象共享一個狀態對象,從而減少系統中對象的個數。

缺點: 1、狀態模式的使用必然會增加系統類和對象的個數。 2、狀態模式的結構與實現都較爲複雜,如果使用不當將導致程序結構和代碼的混亂。 3、狀態模式對"開閉原則"的支持並不太好,對於可以切換狀態的狀態模式,增加新的狀態類需要修改那些負責狀態轉換的源代碼,否則無法切換到新增狀態,而且修改某個狀態類的行爲也需修改對應類的源代碼。

使用場景: 1、行爲隨狀態改變而改變的場景。 2、條件、分支語句的代替者。

注意事項:在行爲受狀態約束的時候使用狀態模式,而且狀態不超過 5 個。

17.觀察者模式 (完成)

何謂觀察者模式?觀察者模式定義了對象之間的一對多依賴關係,這樣一來,當一個對象改變狀態時,它的所有依賴者都會收到通知並且自動更新。

在這裏,發生改變的對象稱之爲觀察目標,而被通知的對象稱之爲觀察者。一個觀察目標可以對應多個觀察者,而且這些觀察者之間沒有相互聯繫,所以麼可以根據需要增加和刪除觀察者,使得系統更易於擴展。所以觀察者提供了一種對象設計,讓主題和觀察者之間以鬆耦合的方式結合。

 觀察者模式包含如下角色:
Subject: 目標
ConcreteSubject: 具體目標
Observer: 觀察者
ConcreteObserver: 具體觀察者

優點: 1、觀察者和被觀察者是抽象耦合的。 2、建立一套觸發機制。

缺點: 1、如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。 2、如果在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發它們之間進行循環調用,可能導致系統崩潰。 3、觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化。

使用場景

一個抽象模型有兩個方面,其中一個方面依賴於另一個方面。將這些方面封裝在獨立的對象中使它們可以各自獨立地改變和複用。
一個對象的改變將導致其他一個或多個對象也發生改變,而不知道具體有多少對象將發生改變,可以降低對象之間的耦合度。
一個對象必須通知其他對象,而並不知道這些對象是誰。
需要在系統中創建一個觸發鏈,A對象的行爲將影響B對象,B對象的行爲將影響C對象……,可以使用觀察者模式創建一種鏈式觸發機制。

注意事項: 1、JAVA 中已經有了對觀察者模式的支持類。 2、避免循環引用。 3、如果順序執行,某一觀察者錯誤會導致系統卡殼,一般採用異步方式。

18.備忘錄模式 (完成)

 後悔藥人人都想要,但是事實卻是殘酷的,根本就沒有後悔藥可買,但是也不僅如此,在軟件的世界裏就有後悔藥!備忘錄模式就是一種後悔藥,它給我們的軟件提供後悔藥的機制,通過它可以使系統恢復到某一特定的歷史狀態。

所謂備忘錄模式就是在不破壞封裝的前提下,捕獲一個對象的內部狀態,並在該對象之外保存這個狀態,這樣可以在以後將對象恢復到原先保存的狀態。它實現了對信息的封裝,使得客戶不需要關心狀態保存的細節。保存就要消耗資源,所以備忘錄模式的缺點就在於消耗資源。如果類的成員變量過多,勢必會佔用比較大的資源,而且每一次保存都會消耗一定的內存。

備忘錄模式包含如下角色:
Originator: 原發器
Memento: 備忘錄
Caretaker: 負責人

 

優點: 1、給用戶提供了一種可以恢復狀態的機制,可以使用戶能夠比較方便地回到某個歷史的狀態。 2、實現了信息的封裝,使得用戶不需要關心狀態的保存細節。

缺點:消耗資源。如果類的成員變量過多,勢必會佔用比較大的資源,而且每一次保存都會消耗一定的內存。

使用場景: 1、需要保存/恢復數據的相關狀態場景。 2、提供一個可回滾的操作。

注意事項: 1、爲了符合迪米特原則,還要增加一個管理備忘錄的類。 2、爲了節約內存,可使用原型模式+備忘錄模式。

19.中介者模式 (完成)

 租房各位都有過的經歷吧!在這個過程中中介結構扮演着很重要的角色,它在這裏起到一箇中間者的作用,給我們和房主互相傳遞信息。在外面軟件的世界裏同樣需要這樣一箇中間者。在我們的系統中有時候會存在着對象與對象之間存在着很強、複雜的關聯關係,如果讓他們之間有直接的聯繫的話,必定會導致整個系統變得非常複雜,而且可擴展性很差!在前面我們就知道如果兩個類之間沒有不必彼此通信,我們就不應該讓他們有直接的關聯關係,如果實在是需要通信的話,我們可以通過第三者來轉發他們的請求。同樣,這裏我們利用中介者來解決這個問題。

 

所謂中介者模式就是用一箇中介對象來封裝一系列的對象交互,中介者使各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。在中介者模式中,中介對象用來封裝對象之間的關係,各個對象可以不需要知道具體的信息通過中介者對象就可以實現相互通信。它減少了對象之間的互相關係,提供了系統可複用性,簡化了系統的結構。

 

在中介者模式中,各個對象不需要互相知道了解,他們只需要知道中介者對象即可,但是中介者對象就必須要知道所有的對象和他們之間的關聯關係,正是因爲這樣就導致了中介者對象的結構過於複雜,承擔了過多的職責,同時它也是整個系統的核心所在,它有問題將會導致整個系統的問題。所以如果在系統的設計過程中如果出現多對多”的複雜關係羣時,千萬別急着使用中介者模式,而是要仔細思考是不是您設計的系統存在問題。

Mediator: 抽象中介者
ConcreteMediator: 具體中介者
Colleague: 抽象同事類
ConcreteColleague: 具體同事類

優點: 1、降低了類的複雜度,將一對多轉化成了一對一。 2、各個類之間的解耦。 3、符合迪米特原則。

缺點:中介者會龐大,變得複雜難以維護。

使用場景: 1、系統中對象之間存在比較複雜的引用關係,導致它們之間的依賴關係結構混亂而且難以複用該對象。 2、想通過一箇中間類來封裝多個類中的行爲,而又不想生成太多的子類。

注意事項:不應當在職責混亂的時候使用。

 

外觀模式、代理模式和中介者模式的區別

 

外觀模式(Facade Pattern

定義一個外觀類,外觀類隱藏系統的複雜性,爲客戶端提供簡化的方法和對現有系統類方法的委託調用。

例如:二手房交易的中介,屬於外觀模式。買房者通過中介可以簡單地買到二手房,中介自己把聯繫房東看房砍價、過戶、交稅這些複雜的事情都搞定了。

 

代理模式(Proxy Pattern

用一個代理類代表另一個類的功能,但是不改變被代理類的功能。目的是控制對被代理類的訪問。

 

中介者模式(Mediator Pattern

用一箇中介對象來封裝一系列的對象交互,中介者使各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。將各對象之間的網狀結構分離爲星型結構。

例如:MVC 框架,其中C(控制器)就是 M(模型)和 V(視圖)的中介者。微信羣是各羣員之間的中介者。

 

20.迭代器模式 (完成)

對於迭代在編程過程中我們經常用到,能夠遊走於聚合內的每一個元素,同時還可以提供多種不同的遍歷方式,這就是迭代器模式的設計動機。在我們實際的開發過程中,我們可能會需要根據不同的需求以不同的方式來遍歷整個對象,但是我們又不希望在聚合對象的抽象接口中充斥着各種不同的遍歷操作,於是我們就希望有某個東西能夠以多種不同的方式來遍歷一個聚合對象,這時迭代器模式出現了。

何爲迭代器模式?所謂迭代器模式就是提供一種方法順序訪問一個聚合對象中的各個元素,而不是暴露其內部的表示。迭代器模式是將迭代元素的責任交給迭代器,而不是聚合對象,我們甚至在不需要知道該聚合對象的內部結構就可以實現該聚合對象的迭代。

通過迭代器模式,使得聚合對象的結構更加簡單,它不需要關注它元素的遍歷,只需要專注它應該專注的事情,這樣就更加符合單一職責原則了。

迭代器模式包含如下角色:
Iterator: 抽象迭代器
ConcreteIterator: 具體迭代器
Aggregate: 抽象聚合類
ConcreteAggregate: 具體聚合類

優點: 1、它支持以不同的方式遍歷一個聚合對象。 2、迭代器簡化了聚合類。 3、在同一個聚合上可以有多個遍歷。 4、在迭代器模式中,增加新的聚合類和迭代器類都很方便,無須修改原有代碼。

缺點:由於迭代器模式將存儲數據和遍歷數據的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的複雜性。

使用場景: 1、訪問一個聚合對象的內容而無須暴露它的內部表示。 2、需要爲聚合對象提供多種遍歷方式。 3、爲遍歷不同的聚合結構提供一個統一的接口。

注意事項:迭代器模式就是分離了集合對象的遍歷行爲,抽象出一個迭代器類來負責,這樣既可以做到不暴露集合的內部結構,又可讓外部代碼透明地訪問集合內部的數據。

https://blog.csdn.net/weixin_41563161/article/details/103661396

21.解釋器模式 (完成)  

所謂解釋器模式就是定義語言的文法,並且建立一個解釋器來解釋該語言中的句子。解釋器模式描述瞭如何構成一個簡單的語言解釋器,主要應用在使用面嚮對象語言開發的編譯器中。它描述瞭如何爲簡單的語言定義一個文法,如何在該語言中表示一個句子,以及如何解釋這些句子。

解釋器模式包含如下角色:
AbstractExpression: 抽象表達式
TerminalExpression: 終結符表達式
NonterminalExpression: 非終結符表達式
Context: 環境類
Client: 客戶類

優點: 1、可擴展性比較好,靈活。 2、增加了新的解釋表達式的方式。 3、易於實現簡單文法。

缺點: 1、可利用場景比較少。 2、對於複雜的文法比較難維護。 3、解釋器模式會引起類膨脹。 4、解釋器模式採用遞歸調用方法。

使用場景: 1、可以將一個需要解釋執行的語言中的句子表示爲一個抽象語法樹。 2、一些重複出現的問題可以用一種簡單的語言來進行表達。 3、一個簡單語法需要解釋的場景。

注意事項:可利用場景比較少,JAVA 中如果碰到可以用 expression4J 代替。

22.命令模式    (完成)

有些時候我們想某個對象發送一個請求,但是我們並不知道該請求的具體接收者是誰,具體的處理過程是如何的,我們只知道在程序運行中指定具體的請求接收者即可,對於這樣將請求封裝成對象的我們稱之爲命令模式。所以命令模式將請求封裝成對象,以便使用不同的請求、隊列或者日誌來參數化其他對象。同時命令模式支持可撤銷的操作。

命令模式可以將請求的發送者和接收者之間實現完全的解耦,發送者和接收者之間沒有直接的聯繫,發送者只需要知道如何發送請求命令即可,其餘的可以一概不管,甚至命令是否成功都無需關心。同時我們可以非常方便的增加新的命令,但是可能就是因爲方便和對請求的封裝就會導致系統中會存在過多的具體命令類。

命令模式包含如下角色:
Command: 抽象命令類
ConcreteCommand: 具體命令類
Invoker: 調用者
Receiver: 接收者
Client:客戶類

優點: 1、降低了系統耦合度。 2、新的命令可以很容易添加到系統中去。

缺點:使用命令模式可能會導致某些系統有過多的具體命令類。

使用場景:認爲是命令的地方都可以使用命令模式,比如: 1、GUI 中每一個按鈕都是一條命令。 2、模擬 CMD。

注意事項:系統需要支持命令的撤銷(Undo)操作和恢復(Redo)操作,也可以考慮使用命令模式,見命令模式的擴展。

23.責任鏈模式 (完成)

職責鏈模式描述的請求如何沿着對象所組成的鏈來傳遞的。它將對象組成一條鏈,發送者將請求發給鏈的第一個接收者,並且沿着這條鏈傳遞,直到有一個對象來處理它或者直到最後也沒有對象處理而留在鏈末尾端。

避免請求發送者與接收者耦合在一起,讓多個對象都有可能接收請求,將這些對象連接成一條鏈,並且沿着這條鏈傳遞請求,直到有對象處理它爲止,這就是職責鏈模式。在職責鏈模式中,使得每一個對象都有可能來處理請求,從而實現了請求的發送者和接收者之間的解耦。同時職責鏈模式簡化了對象的結構,它使得每個對象都只需要引用它的後繼者即可,而不必瞭解整條鏈,這樣既提高了系統的靈活性也使得增加新的請求處理類也比較方便。但是在職責鏈中我們不能保證所有的請求都能夠被處理,而且不利於觀察運行時特徵。

職責鏈模式包含如下角色:
Handler: 抽象處理者
ConcreteHandler: 具體處理者
Client: 客戶類

優點: 1、降低耦合度。它將請求的發送者和接收者解耦。 2、簡化了對象。使得對象不需要知道鏈的結構。 3、增強給對象指派職責的靈活性。通過改變鏈內的成員或者調動它們的次序,允許動態地新增或者刪除責任。 4、增加新的請求處理類很方便。

缺點: 1、不能保證請求一定被接收。 2、系統性能將受到一定影響,而且在進行代碼調試時不太方便,可能會造成循環調用。 3、可能不容易觀察運行時的特徵,有礙於除錯。

使用場景: 1、有多個對象可以處理同一個請求,具體哪個對象處理該請求由運行時刻自動確定。 2、在不明確指定接收者的情況下,向多個對象中的一個提交一個請求。 3、可動態指定一組對象處理請求。

注意事項:在 JAVA WEB 中遇到很多應用。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章