前言 本篇是講述之前學習設計模式的一個總結篇,其目的是為了對這些設計模式的進行一個提煉總結,能夠通過查看看此篇就可以理解一些設計模式的核心思想。 設計模式簡介 什麼是設計模式 設計模式是一套被反覆使用的、多數人知曉的、經過分類編目的、代碼設計經驗的總結。 為什麼使用設計模式 使用設計模式是為了重用代 ...
前言
本篇是講述之前學習設計模式的一個總結篇,其目的是為了對這些設計模式的進行一個提煉總結,能夠通過查看看此篇就可以理解一些設計模式的核心思想。
設計模式簡介
什麼是設計模式
設計模式是一套被反覆使用的、多數人知曉的、經過分類編目的、代碼設計經驗的總結。
為什麼使用設計模式
使用設計模式是為了重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。
設計模式類型
設計模式有23種類型。按照主要分類可以分為三大類:
一、創建型模式
這些設計模式提供了一種在創建對象的同時隱藏創建邏輯的方式,而不是使用 new運算符直接實例化對象。這使得程式在判斷針對某個給定實例需要創建哪些對象時更加靈活。
- 單例模式
- 工廠模式
- 抽象工廠模式
- 建造者模式
- 原型模式
二、結構型模式
這些設計模式關註類和對象的組合。繼承的概念被用來組合介面和定義組合對象獲得新功能的方式。
- 適配器模式
- 橋接模式
- 過濾器模式
- 組合模式
- 裝飾器模式
- 外觀模式
- 享元模式
- 代理模式
三、行為型模式
這些設計模式特別關註對象之間的通信。
- 責任鏈模式
- 命令模式
- 解釋器模式
- 迭代器模式
- 中介者模式
- 備忘錄模式
- 觀察者模式
- 狀態模式
- 空對象模式
- 策略模式
- 模板模式
- 訪問者模式
設計模式的原則
設計模式的六大原則
- 開閉原則:對擴展開放,對修改關閉。
- 里氏代換原則:對開閉原則的補充。任何基類可以出現的地方,子類一定可以出現。LSP 是繼承復用的基石,只有當派生類可以替換掉基類,且軟體單位的功能不受到影響時,基類才能真正被覆用,而派生類也能夠在基類的基礎上增加新的行為。
- 依賴倒轉原則:針對介面編程,依賴於抽象而不依賴於具體。
- 介面隔離原則:儘量使用多個隔離的介面,為了降低類之間的耦合度。
- 迪米特法則:一個實體應當儘量少地與其他實體之間發生相互作用,使得系統功能模塊相對獨立。
- 合成復用原則:儘量使用合成/聚合的方式,而不是使用繼承。
設計模式之間的關係圖:
設計模式總概況:
設計模式相關文章:
- 單例模式
- 工廠方法和抽象工廠模式
- 建造者模式和原型模式
- 適配器模式和橋接模式
- 外觀模式和裝飾器模式
- 組合模式和過濾器模式
- 享元模式和代理模式
- 責任鏈模式和命令模式
- 解釋器模式和迭代器模式
- 訪問者模式和中介者模式
- 策略模式和模板方法模式
- 觀察者模式和空對象模式
創建型模式
單例模式
單例模式介紹
核心就是保證一個系統中的某個類只有一個實例而且該實例易於外界訪問。
單例模式的使用場景
在程式中比較常用的是資料庫連接池、線程池、日誌對象等等。
單例模式使用
單例模式的寫法主要有5種,分別是:
- 餓漢式: 簡單安全, 效率低;
- 飽漢式: 簡單不安全, 效率高 ;
- 靜態內部類: 安全, 效率高;
- 雙重鎖檢查: 複雜安全, 效率高;
- 枚舉單例:簡單安全, 效率高;
單例模式示例圖
單例模式總結
- 構造方法私有化(private);
- 定義一個私有(private)靜態(static)實例化對象;
- 對外提供一個公共(public)靜態(static)的方法得到該實例;
工廠模式
工廠模式主要有三種,簡單工廠模式、工廠方法模式和抽象工廠模式。但是一般的情況下我們主要用到的是工廠方法模式和抽象工廠模式。
工廠方法模式介紹
其核心是定義一個創建對象的介面,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。
工廠方法模式使用場景
比如生活中的汽車製造,大名鼎鼎的hibernate框架在選擇資料庫方言這塊。
工廠方法模式示例圖
抽象工廠模式介紹
主要核心是提供一個創建一系列相關或相互依賴對象的介面,而無需指定它們具體的類。
抽象工廠模式使用場景
比如生活中的服裝製造廠,可以單獨製造衣服、褲子、襪子等等,也可以生產一套服裝。
抽象工廠模式示例圖
建造者模式
建造者模式介紹
使用多個簡單的對象一步一步構建成一個複雜的對象。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
簡單的來說就是將一個複雜的東西抽離出來,對外提供一個簡單的調用,可以在同樣的構建過程創建不同的表示。和工廠模式很相似,不過相比而言更加註重組件的裝配。
建造者模式使用場景
適用一些基本組件不便,但是組合經常變化的時候。比如超市促銷的大禮包。
建造者模式角色
Builder:指定一個抽象的介面,規定該產品所需實現部件的創建,並不涉及具體的對象部件的創建。
ConcreteBuilder:需實現Builder介面,並且針對不同的邏輯,進行不同方法的創建,最終提供該產品的實例。
Director:用來創建複雜對象的部分,對該部分進行完整的創建或者按照一定的規則進行創建。
Product:示被構造的複雜對象。
建造者模式優缺點
優點:
- 建造者獨立,易擴展。
- 便於控制細節風險。
缺點
- 內部結構複雜,不易於理解。
- 產品直接需要有共同點,範圍有控制。
建造者模式示例圖
原型模式
原型模式介紹
用於創建重覆的對象,同時又能保證性能。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。核心是克隆。
原型模式使用場景
- 類初始化的時候需要消耗大量資源的時候;
- 獲取資料庫連接繁瑣的時候;
- 一個對象,有很多個修改者的時候;
原型模式優缺點
優點:
1.可以提升性能;
缺點:
1.因為必須實現Cloneable 介面,所以用起來可能不太方便。
原型模式示例圖
結構型模式
適配器模式
適配器模式介紹
適配器模式是作為兩個不相容的介面之間的橋梁。這種類型的設計模式屬於結構型模式,它結合了兩個獨立介面的功能。簡單的來說就是通過某個介面將不相容的兩個類進行相容,俗稱轉換器。
適配器模式使用
適配器模式主要有兩種類型,一種是類適配器模式,主要通過繼承來實現適配器功能;一種是對象適配器模式,通過組合來實現適配器功能。
適配器模式使用場景
電器的電壓,經典的jdbc使用。
適配器模式優缺點
優點:
提升了類的復用和靈活度。
缺點:
使用過多,系統會比較雜亂,難以把握。
適配器模式示例圖
橋接模式
橋接模式介紹
橋接是用於把抽象化與實現化解耦,使得二者可以獨立變化。這種類型的設計模式屬於結構型模式,它通過提供抽象化和實現化之間的橋接結構,來實現二者的解耦。通過一個中間的橋梁對兩邊的東西進行關聯起來,但是關聯的兩者之間又不相互影響。
橋接模式場景
一個類存在兩個獨立變化的維度,且這兩個維度都需要進行擴展。
橋接模式優缺點
優點:
1、抽象和實現的分離,實現瞭解耦;
2、提升的擴展能力。
缺點:
會使系統看起複雜,對新手不友好,沒有一定的抽象進行設計能力難以理解。
橋接模式示例圖
外觀模式
外觀模式介紹
外觀模式隱藏系統的複雜性,並向客戶端提供了一個客戶端可以訪問系統的介面。它向現有的系統添加一個介面,來隱藏系統的複雜性。對外提供一個簡單介面,隱藏實現的邏輯。
外觀模式使用場景
系統中有多個複雜的模塊或者子系統的時候。
外觀模式優缺點
優點:
降低了耦合,從某種方面來說也提升了安全性。
缺點:
不符合開閉原則,不易更改。
外觀模式示例圖
裝飾器模式
裝飾器模式介紹
裝飾器模式允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是作為現有的類的一個包裝。
把某個東西進行裝飾起來,讓它可以提供一些額外的功能。
裝飾器模式使用場景
原型不變,動態增加一些功能的時候。
裝飾器模式優缺點
優點:
裝飾類和被裝飾類可以獨立發展,耦合度低,易於擴展,靈活方便。
缺點:
過多的對某個類進行裝飾,會增加複雜度。
裝飾器模式示例圖
組合模式
組合模式介紹
組合模式是用於把一組相似的對象當作一個單一的對象。組合模式依據樹形結構來組合對象,用來表示部分以及整體層次。這種類型的設計模式屬於結構型模式,它創建了對象組的樹形結構。
組合模式使用場景
可以表示為 ‘部分-整體’的層級結構。
組合模式優缺點
優點:
高層模塊調用較為簡單,增加某個節點方便。
缺點:
因為其子節點的聲明都是實現類,而不是介面,違反了依賴倒置原則。
組合模式示例圖
過濾器模式
過濾器模式介紹
過濾器模式允許開發人員使用不同的標準來過濾一組對象,通過邏輯運算以解耦的方式把它們連接起來。這種類型的設計模式屬於結構型模式,它結合多個標準來獲得單一標準。
過濾器模式使用場景
需要進行篩選的時候。
過濾器模式優缺點
優點:
簡單,解耦,使用方便。
缺點:
過多使用需要註意性能。
過濾器模式註意事項
在jdk1.8以後可以使用steam的方法進行過濾分組,可以根據指定的條件進行過濾分組篩選。
享元模式
享元模式介紹
享元模式主要用於減少創建對象的數量,以減少記憶體占用和提高性能。這種類型的設計模式屬於結構型模式,它提供了減少對象數量從而改善應用所需的對象結構的方式。
享元模式角色
享元模式的角色主要分為三大類,抽象享元類、具體享元類以及享元工廠類。
- 抽象享元類:所有具體享元類的超類或者介面,通過這個介面,可以接受並作用於外部專題。
- 具體享元類:實現抽象享元類介面的功能並增加存儲空間。
- 享元工廠類:用來創建並管理抽象享元類對象,它主要用來確保合理地共用。每當接受到一個請求是,便會提供一個已經創建的抽象享元類對象或者新建一個。 享元模式的核心在於享元工廠類,享元工廠類的作用在於提供一個用於存儲享元對象的享元池,用戶需要對象時,首先從享元池中獲取,如果享元池中不存在 ,則創建一個新的享元對象返回給用戶,併在享元池中保存該新增對象。
享元模式使用場景
系統有大量相似對象。
享元模式優缺點
優點:
極大的減少對象的創建,從而降低了系統的記憶體,提升了效率。
缺點:
提高了系統的複雜度,因為需要將狀態進行分離成內部和外部,並且也使外部狀態固有化,使得隨著內部狀態的變化而變化,會造成系統的混亂。
享元模式註意事項
需要註意劃分外部狀態和內部狀態,否則可能會引起線程安全問題。 這些類必須有一個工廠對象加以控制。
與單例模式比較
雖然它們在某些方面很像,但是實際上卻是不同的東西,單例模式的目的是限制創建多個對象,避免衝突,比如使用資料庫連接池。而享元模式享元模式的目的是共用,避免多次創建耗費資源,比如使用String類。
享元模式示例圖
代理模式
代理模式介紹
主要是通過一個類代表另一個類的功能。通常,我們創建具有現有對象的對象,以便向外界提供功能介面。
代理模式角色
代理模式主要由這三個角色組成,抽象角色、代理角色和真實角色。
- 抽象角色:通過介面或抽象類聲明真實角色實現的業務方法。
- 代理角色:實現抽象角色,是真實角色的代理,通過真實角色的業務邏輯方法來實現抽象方法,並可以附加自己的操作。
- 真實角色:實現抽象角色,定義真實角色所要實現的業務邏輯,供代理角色調用。
代理模式使用
代理模式又分為靜態代理、動態代理。
- 靜態代理是由程式員創建或工具生成代理類的源碼,再編譯代理類。所謂靜態也就是在程式運行前就已經存在代理類的位元組碼文件,代理類和委托類的關係在運行前就確定了。
- 動態代理是在實現階段不用關心代理類,而在運行階段才指定哪一個對象。可以使用JDK中
java.lang.reflect
來進行開發。
代理模式使用場景
1、遠程代理。
2、虛擬代理。
3、Copy-on-Write 代理。
4、保護(Protect or Access)代理。
5、Cache代理。
6、防火牆(Firewall)代理。
7、同步化(Synchronization)代理。
8、智能引用(SmartReference)代理。
代理模式優缺點
優點:
1、職責清晰。
2、高擴展性。
3、智能化。
缺點:
1、由於在客戶端和真實主題之間增加了代理對象,因此有些類型的代理模式可能會造成請求的處理速度變慢。
2、實現代理模式需要額外的工作,有些代理模式的實現非常複雜。
代理模式註意事項
和適配器模式的區別:適配器模式主要改變所考慮對象的介面,而代理模式不能改變所代理類的介面。
和裝飾器模式的區別:裝飾器模式為了增強功能,而代理模式是為了加以控制。
代理模式示例圖
行為型模式
責任鏈模式
責任鏈模式介紹
責任鏈模式顧名思義,就是為請求創建了一個接收者對象的鏈。這種模式給予請求的類型,對請求的發送者和接收者進行解耦。這種類型的設計模式屬於行為型模式。在這種模式中,通常每個接收者都包含對另一個接收者的引用。如果一個對象不能處理該請求,那麼它會把相同的請求傳給下一個接收者,依此類推。
簡單的理解的話就是進行層級處理。
責任鏈模式角色
責任鏈模式主要由這三個角色組成,請求接收者介面(Handler)、請求實現者類(ConcreteHandler)和請求發送者(Client)。
- 請求接收者介面:定義可以處理客戶端請求事項的介面,包含“可鏈接下一個同樣能處理請求”的對象引用。
- 請求實現者類:實現請求處理介面,並判斷對象本身是否能夠處理本次請求,如果不能完成請求,則交由後繼者來處理。
- 請求發送者:將請求發送給第一個接收者對象,並等待請求的回覆。
責任鏈模式使用場景
需要動態指定處理某一組請求時,在不確定接受者的的情況下,向多個對象發送請求時。
責任鏈模式優缺點
優點:
耦合度低,請求者和執行者並沒有必然的聯繫;
靈活度高,可以通過內部成員來進行更改它們執行的次序;
擴展性好,Handler的子類擴展非常方便。
缺點:
會在某程度上降低程式的性能,設置不當的話可能會出現迴圈調用。
在鏈過長時,會降低代碼的閱讀性以及增加代碼的複雜度。
責任鏈模式註意事項
雖然責任鏈模式很靈活,但是犧牲的是一定的性能,因為責任鏈模式是層級處理,在處理數據的有一定的延遲,所所以需要低延遲的情況下,不推薦使用責任鏈模式。
責任鏈模式示例圖
命令模式
命令模式介紹
命令模式顧名思義,是一種數據驅動的設計模式,它屬於行為型模式。請求以命令的形式包裹在對象中,並傳給調用對象。調用對象尋找可以處理該命令的合適的對象,並把該命令傳給相應的對象,該對象執行命令。
也就是將一個請求封裝成一個對象,從而可以用不同的請求對客戶進行參數化。
命令模式角色
命令模式主要由這三個角色組成,命令對象(command)、命令執行對象(received)和命令請求對象(invoker)。
- 命令對象:通過介面或抽象類聲明實現的方法。
- 命令執行對象:實現命令對象的方法,並將一個接收者和動作進行綁定,調用接收者相應的操作。
- 命令請求對象:用於執行這個請求,可以動態的對命令進行控制。
命令模式使用場景
如果在有類似
命令
需要指定的,就可以用命令模式,比如記錄日誌、撤銷操作命令等。
命令模式優缺點
優點:
耦合度低,請求者和執行者並沒有必然的聯繫;
擴展性好,Command的子類可以非常容易地擴展。
缺點:
如果命令過多的話,會增加系統的複雜度 。
命令模式示例圖
解釋器模式
解釋器模式介紹
解釋器模式顧名思義,就是對某事物進行解釋。給定一個語言之後,解釋器模式可以定義出其文法的一種表示,並同時提供一個解釋器。客戶端可以使用這個解釋器來解釋這個語言中的句子。
解釋器模式其實就是對某事物進行解釋。
解釋器模式角色
解釋器模式主要由這四個角色組成,抽象表達式(Expression)角色、終結符表達式(Terminal Expression)角色、非終結符表達式(Nonterminal Expression)角色和環境(Context)角色。
- 抽象解釋器:聲明一個所有具體表達式都要實現的抽象介面(或者抽象類),介面中主要是一個interpret()方法,稱為解釋操作。具體解釋任務由它的各個實現類來完成,具體的解釋器分別由終結符解釋器TerminalExpression和非終結符解釋器NonterminalExpression完成。
- 終結符表達式:實現與文法中的元素相關聯的解釋操作,通常一個解釋器模式中只有一個終結符表達式,但有多個實例,對應不同的終結符。終結符一半是文法中的運算單元,比如有一個簡單的公式R=R1+R2,在裡面R1和R2就是終結符,對應的解析R1和R2的解釋器就是終結符表達式。
- 非終結符表達式:文法中的每條規則對應於一個非終結符表達式,非終結符表達式一般是文法中的運算符或者其他關鍵字,比如公式R=R1+R2中,+就是非終結符,解析+的解釋器就是一個非終結符表達式。非終結符表達式根據邏輯的複雜程度而增加,原則上每個文法規則都對應一個非終結符表達式。
- 環境角色:這個角色的任務一般是用來存放文法中各個終結符所對應的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些信息需要存放到環境角色中,很多情況下我們使用Map來充當環境角色就足夠了。
解釋器模式使用場景
一個簡單的語法規則需要解釋的場景,比如sql。
有重覆的問題的時候。
解釋器模式優缺點
優點:
擴展性好,子類擴展非常方便。
實現簡單。
缺點:
可使用的場景比較少;
類過多的話,會使代碼臃腫,難以維護;
解釋器模式示例圖
迭代器模式
迭代器模式介紹
迭代器模式用於順序訪問集合對象的元素,不需要知道集合對象的底層表示,屬於行為型模式。 它提供一種方法順序訪問一個聚合對象中各個元素, 而又無須暴露該對象的內部表示。
迭代器模式角色
迭代器模式主要由這四個角色組成,迭代器角色(Iterator)、具體迭代器角色(Concrete Iterator)、容器角色(Container)和具體容器角色(Concrete Container)。
- 迭代器角色(Iterator):通過介面或抽象類聲明實現的方法。
- 具體迭代器角色(Concrete Iterator):具體迭代器角色要實現迭代器介面,並要記錄遍歷中的當前位置。
- 容器角色(Container):容器角色負責提供創建具體迭代器角色的介面。
- 具體容器角色(Concrete Container):具體容器角色實現創建具體迭代器角色的介面——這個具體迭代器角色於該容器的結構相關。
迭代器模式使用場景
需要為聚合對象提供遍歷的功能的時候。
迭代器模式優缺點
優點:
靈活度高,可以通過不同的方式遍歷對象;
擴展性好,可以很方便的增加新的聚合類和迭代器類而不用修改之前的代碼。
缺點:
由於迭代器模式將存儲數據和遍曆數據的職責分離,增加新的聚合類需要對應增加新的迭代器類,類的個數成對增加,這在一定程度上增加了系統的複雜性。
迭代器模式示例圖
訪問者模式
訪問者模式介紹
訪問者模式(VisitorPattern),顧名思義使用了這個模式後就可以在不修改已有程式結構的前提下,通過添加額外的訪問者來完成對已有代碼功能的提升,它屬於行為模式。訪問者模式的目的是封裝一些施加於某種數據結構元素之上的操作。一旦這些操作需要修改的話,接受這個操作的數據結構則可以保持不變。
其主要目的是將數據結構與數據操作分離。
訪問者模式角色
訪問者模式主要由這五個角色組成,抽象訪問者(Visitor)、具體訪問者(ConcreteVisitor)、抽象節點(Node)、具體節點(ConcreteNode)和結構對象(ObjectStructure)。
- 抽象訪問者(Visitor)角色:聲明瞭一個或者多個方法操作,形成所有的具體訪問者角色必須實現的介面。
- 具體訪問者(ConcreteVisitor)角色:實現抽象訪問者所聲明的介面,也就是抽象訪問者所聲明的各個訪問操作。
- 抽象節點(Node)角色:聲明一個接受操作,接受一個訪問者對象作為一個參數。
- 具體節點(ConcreteNode)角色:實現了抽象節點所規定的接受操作。
- 結構對象(ObjectStructure)角色:有如下的責任,可以遍歷結構中的所有元素。
訪問者模式使用場景
對象結構中對象對應的類很少改變,但經常需要在此對象結構上定義新的操作;
需要對一個對象結構中的對象進行很多不同的並且不相關的操作,而需要避免讓這些操作"污染"這些對象的類,也不希望在增加新操作時修改這些類。
訪問者模式優缺點
訪問者模式優點:
擴展性好,可以在不修改對象結構中的元素的情況下,為對象結構中的元素添加新的功能;
符合單一職責原則,通過訪問者將無關的行為分離,使職責單一;
訪問者模式缺點:
違反了迪米特原則,因為具體元素對訪問者公佈細節;
違反了依賴倒置原則,依賴了具體類,沒有依賴抽象;
對象結構變化困難,若對象結構發生了改變,訪問者的介面和訪問者的實現也都要發生相應的改變;
訪問者模式示例圖
中介者模式
中介者模式介紹
中介者模式(Mediator Pattern),定義了一個中介對象來封裝一系列對象之間的交互關係。中介者使各個對象之間不需要顯式地相互引用,從而使耦合性降低,而且可以獨立地改變它們之間的交互行為,屬於行為型模式。
其主要的目的是用來降低多個對象和類之間的通信複雜性。
中介者模式角色
中介者模式主要由這四個角色組成, 抽象中介者(Mediator)、具體中介者(ConcreteMediator)、 抽象同事類(Colleague)和具體同事類(ConcreteColleague) 。
- 抽象中介者(Mediator): 定義了同事對象到中介者對象之間的介面。
- 具體中介者(ConcreteMediator): 實現抽象中介者的方法,它需要知道所有的具體同事類,同時需要從具體的同事類那裡接收信息,並且向具體的同事類發送信息。
- 抽象同事類(Colleague): 定義了中介者對象的介面,它只知道中介者而不知道其他的同事對象。
- 具體同事類(ConcreteColleague) : 每個具體同事類都只需要知道自己的行為即可,但是他們都需要認識中介者。
中介者模式使用場景
通過一個中間類來封裝多個類中的行為,而又不想生成太多的子類。
中介者模式優缺點
優點:
靈活性高,因為將同事類進行瞭解耦,使其不必有關聯性;
降低了類的複雜度,將一對多轉化成了一對一;
缺點:
中介者使用過多,會使系統變得複雜難以維護;
中介者模式註意事項
若不明確各個類的職責,那麼就不要進行使用!
和外觀模式、代理模式比較
中介者模式和外觀模式、代理模式比較類似,但是又有不同。
和外觀模式比較,中介者模式中,同事類必須依賴與中介者,中介者也知道同事類;但是外觀模式中,子系統是不需要知道外觀類的存在,並且子系統是可以脫離外觀模式的。
和代理模式,代理模式的核心就是代理作用,主要還是對原先的類進行擴展或增加控制,比如進行許可權控制;而中介者模式主要目的是為了減少對象之前的耦合,也就是同事類直接相互獨立,互不影響。
中介者模式示例圖
策略模式
策略模式介紹
策略模式(Strategy Pattern)屬於對象的行為模式。其用意是針對一組演算法,將每一個演算法封裝到具有共同介面的獨立的類中,從而使得它們可以相互替換。策略模式使得演算法可以在不影響到客戶端的情況下發生變化。
其主要目的是通過定義相似的演算法,替換if else 語句寫法,並且可以隨時相互替換。
策略模式角色
策略模式主要由這三個角色組成,環境角色(Context)、抽象策略角色(Strategy)和具體策略角色(ConcreteStrategy)。
- 環境角色(Context):持有一個策略類的引用,提供給客戶端使用。
- 抽象策略角色(Strategy):這是一個抽象角色,通常由一個介面或抽象類實現。此角色給出所有的具體策略類所需的介面。
- 具體策略角色(ConcreteStrategy):包裝了相關的演算法或行為。
策略模式使用場景
如果在一個系統裡面有許多類,它們之間的區別僅在於它們的行為,那麼使用策略模式可以動態地讓一個對象在許多行為中選擇一種行為;
一個系統需要動態地在幾種演算法中選擇一種;
如果一個對象有很多的行為,如果不用恰當的模式,這些行為就只好使用多重的條件選擇語句來實現;
策略模式優缺點
優點:
擴展性好,可以在不修改對象結構的情況下,為新的演算法進行添加新的類進行實現;
靈活性好,可以對演算法進行自由切換;
缺點:
使用策略類變多,會增加系統的複雜度。;
客戶端必須知道所有的策略類才能進行調用;
策略模式示例圖
模板模式
模板模式介紹
模板模式(Template Pattern)中,一個抽象類公開定義了執行它的方法的方式/模板。它的子類可以按需要重寫方法實現,但調用將以抽象類中定義的方式進行。 這種類型的設計模式屬於行為型模式。定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。
模板模式,其主要的的思想就是做一個模板,提供給客戶端進行調用。
模板模式角色
模板模式主要由抽象模板(Abstract Template)角色和具體模板(Concrete Template)角色組成。
抽象模板(Abstract Template): 定義了一個或多個抽象操作,以便讓子類實現。這些抽象操作叫做基本操作,它們是一個頂級邏輯的組成步驟;定義並實現了一個模板方法。這個模板方法一般是一個具體方法,它給出了一個頂級邏輯的骨架,而邏輯的組成步驟在相應的抽象操作中,推遲到子類實現。頂級邏輯也有可能調用一些具體方法。
具體模板(Concrete Template): 實現父類所定義的一個或多個抽象方法,它們是一個頂級邏輯的組成步驟;每一個抽象模板角色都可以有任意多個具體模板角色與之對應,而每一個具體模板角色都可以給出這些抽象方法(也就是頂級邏輯的組成步驟)的不同實現,從而使得頂級邏輯的實現各不相同。
模板模式使用場景
有多個子類共有邏輯相同的方法;
重要的、複雜的方法,可以考慮作為模板方法。
模板模式優缺點
優點:
擴展性好,對不變的代碼進行封裝,對可變的進行擴展;
可維護性好,因為將公共代碼進行了提取,使用的時候直接調用即可;
缺點:
因為每一個不同的實現都需要一個子類來實現,導致類的個數增加,會使系統變得複雜;
模板模式註意事項
為防止惡意操作,一般模板方法都加上 final 關鍵詞!
模板模式示例圖
備忘錄模式
備忘錄模式介紹
備忘錄模式(Memento Pattern)用於保存一個對象的某個狀態,以便在適當的時候恢復對象,該模式屬於行為型模式。
其主要目的是在不破壞封裝性的前提下,捕獲一個對象的內部狀態,併在該對象之外保存這個狀態。
其主要的的思想就是備份。
備忘錄模式角色
備忘錄模式主要由這三個角色組成,備忘錄角色(Memento)、發起人角色(Originator)和負責人(Caretaker)角色。
- 備忘錄(Memento):主要的功能是包含要被恢復的對象的狀態。
- 發起人(Originator):在創建的時候,會在備忘錄對象中存儲狀態。
- 負責人(Caretaker):主要是負責從備忘錄對象中恢復對象的狀態。
備忘錄模式使用場景
需要保存/恢複數據的相關狀態場景;
備忘錄模式優缺點
優點
給用戶提供了一種可以恢復狀態的機制,可以使用戶能夠比較方便地回到某個歷史的狀態;
實現了信息的封裝,使得用戶不需要關心狀態的保存細節;
缺點
非常的消耗資源;
客戶端必須知道所有的策略類才能進行調用;
備忘錄模示例圖
狀態模式
狀態模式介紹
狀態模式(State Pattern)屬於行為型模式,其狀態的對象和一個行為隨著狀態對象改變而改變。
其主要目的解決的是當控制一個對象狀態轉換的條件表達式過於複雜是的情況。把狀態的判斷邏輯轉移到表示不同狀態一系列類中,可以把複雜的判斷簡單化。
主要的的思想就是提供一種狀態,提供給客戶端進行調用。
狀態模式角色
狀態模式主要由環境角色(Context)、 抽象狀態(State)和具體狀態(Concrete State)組成。
環境角色(Context): 它定義了客戶程式需要的介面並維護一個具體狀態角色的實例,將與狀態相關的操作委托給當前的具體狀態對象來處理。
- 抽象狀態角色(State): 定義一個介面以封裝使用上下文環境的的一個特定狀態相關的行為。
具體狀態角色(Concrete State):實現抽象狀態定義的介面。
狀態模式使用場景
行為隨狀態改變而改變的場景;
條件、分支語句的代替者。
狀態模式優缺點
優點:
擴展性好,將和狀態有關的行為放到一起,增加新的的狀態,只需要改變對象狀態即可改變對象的行為即可;
復用性好,讓多個環境對象共用一個狀態對象,從而減少系統中對象的個數;
缺點:
使用狀態模式會增加系統類和對象的個數,並且該模式的結構與實現都較為複雜,如果使用不當將導致程式結構和代碼的混亂;
狀態模式對"開閉原則"的支持並不太好,對於可以切換狀態的狀態模式,增加新的狀態類需要修改那些負責狀態轉換的源代碼,否則無法切換到新增狀態,而且修改某個狀態類的行為也需修改對應類的源代碼。
狀態模式註意事項
在行為受狀態約束的時候使用狀態模式,而且狀態不超過5個。
和策略模式比較
在學習狀態模式的時候,很容易和策略模式搞混,因為它們實在是太像了,很難區分,在查閱一番資料之後,整理瞭如下的相同點和區別點。
相同點:
- 它們很容易添加新的狀態或策略,而且不需要修改使用它們的Context對象。
- 它們都符合OCP原則,在狀態模式和策略模式中,Context對象對修改是關閉的,添加新的狀態或策略,都不需要修改Context。
- 它們都會初始化。
- 它們都依賴子類去實現相關行為。
區別點
- 狀態模式的行為是平行性的,不可相互替換的;
- 而策略模式的行為是平等性的,是可以相互替換的。
- 最重要的一個不同之處是,策略模式的改變由客戶端完成;
- 而狀態模式的改變,由環境角色或狀態自己.
狀態模式示例圖
觀察者模式
觀察者模式介紹
觀察者模式又叫發佈-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式。觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。。
其主要目的是定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。
觀察者模式角色
觀察者模式主要由這四個角色組成,抽象主題角色(Subject)、具體主題角色(ConcreteSubject)、抽象觀察者角色(Observer)和具體觀察者角色(ConcreteObserver)。
- 抽象主題角色(Subject):它把所有觀察者對象的引用保存到一個聚集里,每個主題都可以有任何數量的觀察者。抽象主題提供一個介面,可以增加和刪除觀察者對象。
- 具體主題角色(ConcreteSubject):將有關狀態存入具體觀察者對象;在具體主題內部狀態改變時,給所有登記過的觀察者發出通知。
- 抽象觀察者角色(Observer):主要是負責從備忘錄對象中恢復對象的狀態。
觀察者模式使用場景
需要關聯行為的場景;
事件需要創建一個觸發鏈的場景,比如監控;
跨系統的消息交換場景,比如消息隊列、事件匯流排的處理機制。
觀察者模式優缺點
優點:
解除耦合,讓耦合的雙方都依賴於抽象,從而使得各自的變換都不會影響另一邊的變換。
缺點
如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間;
如果在觀察者和觀察目標之間有迴圈依賴的話,觀察目標會觸發它們之間進行迴圈調用,可能導致系統崩潰;
觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化。
觀察者模式註意事項
如果順序執行,某一觀察者錯誤會導致系統卡殼,建議採用非同步方式。
觀察者模式示例圖
空對象模式
空對象模式介紹
空對象模式(NullObject Pattern)主要是通過一個空對象取代 NULL 對象實例的檢查。Null 對象不是檢查空值,而是反應一個不做任何動作的關係。 這樣的Null 對象也可以在數據不可用的時候提供預設的行為。
其主要目的是在進行調用是不返回Null,而是返回一個空對象,防止空指針異常。
空對象模式使用場景
需要大量對空值進行判斷的時候;
空對象模式優缺點
優點:
可以加強系統的穩固性,能有效防止空指針報錯對整個系統的影響;
不依賴客戶端便可以保證系統的穩定性;
缺點:
需要編寫較多的代碼來實現空值的判斷,從某種方面來說不划算;
其它
在學習設計模式的時候,主要參考書籍是《大話設計模式》以及菜鳥教程的設計模式介紹。
其實在我們學習了這麼多的設計模式中,大部分可能只是聽說瞭解過,真正經常使用的設計模式也無外乎就那幾種,單例模式(資料庫、線程池場景)、工廠模式(簡單的crud操作中實例化的model)、策略模式(商城會員、優惠打折場景)、觀察者模式(消息推送場景)、代理模式(主要是動態代理這塊)、外觀模式(一鍵調用)、裝飾器模式(錦上添花場景),但是也不全這樣,使用設計模式最好根據實際的場景來使用,否則可能在不合適的場景使用了不適合的設計模式而導致代碼混亂。
音樂推薦
往期音樂推薦
一、
我們目送 那漸漸消失的行跡雲 在晃眼間消逝 總是如此短暫 如像昨天起 不變的事 始終不會改變 不該存在的東西 帶著遺憾消失在指間
那鳥兒還未能展翅高飛 但它總有一天會破風馳行 遙不可及的地方仍在遠處 所以只能凝視深藏的願望 孩子們走在盛夏的鐵路上 流風輕撫著他們的赤腳 遠離了童年
二、
這世上大部分失落,都是因為我們自己沒成為更好的自己,卻奢求別人成為更好的別人。
三、
平靜孤寂的調子起頭,兩個人分開之後的沉寂 頹廢,慢慢的音階起伏,我意識到不能這樣下去,我開始改變現狀,變得積極。到高潮部分 我不在頹廢,我走了新的目標 我迎著太陽前進。我想這就是You的含義,你是我的一段過去
四、
扶桑畫師淺溪,居泰安,喜繪鯉。院前一方荷塘,錦鯉游曳,溪常與嬉戲。 其時正武德之亂,藩鎮割據,戰事頻仍,魑魅魍魎,肆逆於道。兵戈逼泰安,街鄰皆逃亡,獨溪不捨錦鯉,未去。 是夜,院室倏火。有人入火護溪,言其本鯉中妖,欲取溪命,卻生情愫,遂不忍為之。翌日天明,火勢漸歇,人已不見。
五、
稚兒擎瓜柳棚下,細犬逐蝶窄巷中,人間繁華多笑語,惟我空餘兩鬢風。
六、
散落的花,火的碎片 誘人的夏夜終結
漸漸 天空閃耀,帶著誰許的願
突然綻放的煙花
美麗如夢幻,遲來脆弱的夏天
夜空中,火花舞動在今夜
枝頭落下的仲夏夜之夢
愉快的涼風,熱帶的夜
天空飄著細雨,在喧鬧的蟬鳴時節
夏末,秋天指向路邊。
七、
論如何一個人在家嗨成狗。取下耳機無限的孤獨感。帶上耳機卧槽我是全世界。
八、
我渴望能見你一面,但請你記得,我不會開口要求見你。這不是因為驕傲,你知道我在你面前毫無驕傲可言,而是因為,唯有你也想見我的時候,我們見面才有意義。 ———《越洋情書》
九、
就算是Believe,中間也藏了一個lie;
就算是Friend,還是免不了end;
就算是Lover,還可能會over;
就算是Wife,心裡也夾雜著if;
欣慰的是:即便是Forget,也曾經get,
就算impossible,但還藏著possible。
十、
人有三樣東西是無法隱瞞的,咳嗽、窮困和愛;你想隱瞞越欲蓋彌彰。人有三樣東西是不該揮霍的,身體、金錢和愛;你想揮霍卻得不償失。人有三樣東西是無法輓留的,時間、生命和愛;你想輓留卻漸行漸遠。人有三樣東西是不該回憶的,災難、死亡和愛;你想回憶卻苦不堪言。 ——《洛麗塔》
十一、
簡單,重覆,毫無華麗旋律,也無厚重悲涼的伴奏。但心偏偏就被緊緊的抓住了。一種茫然卻被迫緊湊的感覺。一種不知何所處的心虛。what for?
十二、
輕吟一句情話,執筆一副情畫。 綻放一地情花,覆蓋一片青瓦。 共飲一杯清茶,同研一碗青砂。
輓起一面輕紗,看清天邊月牙。愛像水墨青花,何懼剎那芳華。
十三、
所有人和事,自己問心無愧就好,不是你的也別強求,反正離去的,都是風景,留下的,才是人生。
以上評論來自網易雲!
項目的代碼
java-study是本人在學習Java過程中記錄的一些代碼,也包括之前博文中使用的代碼。如果感覺不錯,希望順手給個start,當然如果有不足,也希望提出。
github地址: https://github.com/xuwujing/java-study
原創不易,如果感覺不錯,希望給個推薦!您的支持是我寫作的最大動力!
版權聲明:
作者:虛無境
博客園出處:http://www.cnblogs.com/xuwujing
CSDN出處:http://blog.csdn.net/qazwsxpcm
個人博客出處:http://www.panchengming.com