天天看點

Java進階篇 設計模式之十四 ----- 總結篇

本篇是講述之前學習設計模式的一個總結篇,其目的是為了對這些設計模式的進行一個提煉總結,能夠通過檢視看此篇就可以了解一些設計模式的核心思想。

設計模式是一套被反複使用的、多數人知曉的、經過分類編目的、代碼設計經驗的總結。
使用設計模式是為了重用代碼、讓代碼更容易被他人了解、保證代碼可靠性。

設計模式有23種類型。按照主要分類可以分為三大類:

一、建立型模式

這些設計模式提供了一種在建立對象的同時隐藏建立邏輯的方式,而不是使用 new運算符直接執行個體化對象。這使得程式在判斷針對某個給定執行個體需要建立哪些對象時更加靈活。

單例模式

工廠模式

抽象工廠模式

建造者模式

原型模式

二、結構型模式

這些設計模式關注類和對象的組合。繼承的概念被用來組合接口和定義組合對象獲得新功能的方式。

擴充卡模式

橋接模式

過濾器模式

組合模式

裝飾器模式

外觀模式

享元模式

代理模式

三、行為型模式

這些設計模式特别關注對象之間的通信。

責任鍊模式

指令模式

解釋器模式

疊代器模式

中介者模式

備忘錄模式

觀察者模式

狀态模式

空對象模式

政策模式

模闆模式

通路者模式

設計模式的六大原則

開閉原則:對擴充開放,對修改關閉。

裡氏代換原則:對開閉原則的補充。任何基類可以出現的地方,子類一定可以出現。LSP 是繼承複用的基石,隻有當派生類可以替換掉基類,且軟體機關的功能不受到影響時,基類才能真正被複用,而派生類也能夠在基類的基礎上增加新的行為。

依賴倒轉原則:針對接口程式設計,依賴于抽象而不依賴于具體。

接口隔離原則:盡量使用多個隔離的接口,為了降低類之間的耦合度。

迪米特法則:一個實體應當盡量少地與其他實體之間發生互相作用,使得系統功能子產品相對獨立。

合成複用原則:盡量使用合成/聚合的方式,而不是使用繼承。

設計模式之間的關系圖:

Java進階篇 設計模式之十四 ----- 總結篇

設計模式總概況:

Java進階篇 設計模式之十四 ----- 總結篇

設計模式相關文章:

工廠方法和抽象工廠模式

建造者模式和原型模式

擴充卡模式和橋接模式

外觀模式和裝飾器模式

組合模式和過濾器模式

享元模式和代理模式

責任鍊模式和指令模式

解釋器模式和疊代器模式

通路者模式和中介者模式

政策模式和模闆方法模式

觀察者模式和空對象模式

核心就是保證一個系統中的某個類隻有一個執行個體而且該執行個體易于外界通路。

在程式中比較常用的是資料庫連接配接池、線程池、日志對象等等。

單例模式的寫法主要有5種,分别是:

餓漢式: 簡單安全, 效率低;

飽漢式: 簡單不安全, 效率高 ;

靜态内部類: 安全, 效率高;

雙重鎖檢查: 複雜安全, 效率高;

枚舉單例:簡單安全, 效率高;

Java進階篇 設計模式之十四 ----- 總結篇

構造方法私有化(private);

定義一個私有(private)靜态(static)執行個體化對象;

對外提供一個公共(public)靜态(static)的方法得到該執行個體;

工廠模式主要有三種,簡單工廠模式、工廠方法模式和抽象工廠模式。但是一般的情況下我們主要用到的是工廠方法模式和抽象工廠模式。

其核心是定義一個建立對象的接口,讓其子類自己決定執行個體化哪一個工廠類,工廠模式使其建立過程延遲到子類進行。

比如生活中的汽車制造,大名鼎鼎的hibernate架構在選擇資料庫方言這塊。

Java進階篇 設計模式之十四 ----- 總結篇
主要核心是提供一個建立一系列相關或互相依賴對象的接口,而無需指定它們具體的類。

比如生活中的服裝制造廠,可以單獨制造衣服、褲子、襪子等等,也可以生産一套服裝。

Java進階篇 設計模式之十四 ----- 總結篇
使用多個簡單的對象一步一步建構成一個複雜的對象。這種類型的設計模式屬于建立型模式,它提供了一種建立對象的最佳方式。 簡單的來說就是将一個複雜的東西抽離出來,對外提供一個簡單的調用,可以在同樣的建構過程建立不同的表示。和工廠模式很相似,不過相比而言更加注重元件的裝配。

适用一些基本元件不便,但是組合經常變化的時候。比如超市促銷的大禮包。

Builder:指定一個抽象的接口,規定該産品所需實作部件的建立,并不涉及具體的對象部件的建立。

ConcreteBuilder:需實作Builder接口,并且針對不同的邏輯,進行不同方法的建立,最終提供該産品的執行個體。

Director:用來建立複雜對象的部分,對該部分進行完整的建立或者按照一定的規則進行建立。

Product:示被構造的複雜對象。

優點:

建造者獨立,易擴充。

便于控制細節風險。

缺點

内部結構複雜,不易于了解。

産品直接需要有共同點,範圍有控制。

Java進階篇 設計模式之十四 ----- 總結篇
用于建立重複的對象,同時又能保證性能。這種類型的設計模式屬于建立型模式,它提供了一種建立對象的最佳方式。核心是克隆。

類初始化的時候需要消耗大量資源的時候;

擷取資料庫連接配接繁瑣的時候;

一個對象,有很多個修改者的時候;

1.可以提升性能;

缺點:

1.因為必須實作Cloneable 接口,是以用起來可能不太友善。

Java進階篇 設計模式之十四 ----- 總結篇
擴充卡模式是作為兩個不相容的接口之間的橋梁。這種類型的設計模式屬于結構型模式,它結合了兩個獨立接口的功能。簡單的來說就是通過某個接口将不相容的兩個類進行相容,俗稱轉換器。
擴充卡模式主要有兩種類型,一種是類擴充卡模式,主要通過繼承來實作擴充卡功能;一種是對象擴充卡模式,通過組合來實作擴充卡功能。

電器的電壓,經典的jdbc使用。

提升了類的複用和靈活度。
使用過多,系統會比較雜亂,難以把握。
Java進階篇 設計模式之十四 ----- 總結篇
橋接是用于把抽象化與實作化解耦,使得二者可以獨立變化。這種類型的設計模式屬于結構型模式,它通過提供抽象化和實作化之間的橋接結構,來實作二者的解耦。通過一個中間的橋梁對兩邊的東西進行關聯起來,但是關聯的兩者之間又不互相影響。
一個類存在兩個獨立變化的次元,且這兩個次元都需要進行擴充。
1、抽象和實作的分離,實作了解耦; 2、提升的擴充能力。
會使系統看起複雜,對新手不友好,沒有一定的抽象進行設計能力難以了解。
Java進階篇 設計模式之十四 ----- 總結篇
外觀模式隐藏系統的複雜性,并向用戶端提供了一個用戶端可以通路系統的接口。它向現有的系統添加一個接口,來隐藏系統的複雜性。對外提供一個簡單接口,隐藏實作的邏輯。
系統中有多個複雜的子產品或者子系統的時候。
降低了耦合,從某種方面來說也提升了安全性。
不符合開閉原則,不易更改。
Java進階篇 設計模式之十四 ----- 總結篇
裝飾器模式允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬于結構型模式,它是作為現有的類的一個包裝。 把某個東西進行裝飾起來,讓它可以提供一些額外的功能。
原型不變,動态增加一些功能的時候。
裝飾類和被裝飾類可以獨立發展,耦合度低,易于擴充,靈活友善。
過多的對某個類進行裝飾,會增加複雜度。
Java進階篇 設計模式之十四 ----- 總結篇
組合模式是用于把一組相似的對象當作一個單一的對象。組合模式依據樹形結構來組合對象,用來表示部分以及整體層次。這種類型的設計模式屬于結構型模式,它建立了對象組的樹形結構。
可以表示為 ‘部分-整體’的層級結構。
高層子產品調用較為簡單,增加某個節點友善。
因為其子節點的聲明都是實作類,而不是接口,違反了依賴倒置原則。
Java進階篇 設計模式之十四 ----- 總結篇
過濾器模式允許開發人員使用不同的标準來過濾一組對象,通過邏輯運算以解耦的方式把它們連接配接起來。這種類型的設計模式屬于結構型模式,它結合多個标準來獲得單一标準。
需要進行篩選的時候。

優點:

簡單,解耦,使用友善。

缺點:

過多使用需要注意性能。
在jdk1.8以後可以使用steam的方法進行過濾分組,可以根據指定的條件進行過濾分組篩選。
享元模式主要用于減少建立對象的數量,以減少記憶體占用和提高性能。這種類型的設計模式屬于結構型模式,它提供了減少對象數量進而改善應用所需的對象結構的方式。

享元模式的角色主要分為三大類,抽象享元類、具體享元類以及享元工廠類。

抽象享元類:所有具體享元類的超類或者接口,通過這個接口,可以接受并作用于外部專題。

具體享元類:實作抽象享元類接口的功能并增加存儲空間。

享元工廠類:用來建立并管理抽象享元類對象,它主要用來確定合理地共享。每當接受到一個請求是,便會提供一個已經建立的抽象享元類對象或者建立一個。 享元模式的核心在于享元工廠類,享元工廠類的作用在于提供一個用于存儲享元對象的享元池,使用者需要對象時,首先從享元池中擷取,如果享元池中不存在 ,則建立一個新的享元對象傳回給使用者,并在享元池中儲存該新增對象。

系統有大量相似對象。
極大的減少對象的建立,進而降低了系統的記憶體,提升了效率。
提高了系統的複雜度,因為需要将狀态進行分離成内部和外部,并且也使外部狀态固有化,使得随着内部狀态的變化而變化,會造成系統的混亂。
需要注意劃分外部狀态和内部狀态,否則可能會引起線程安全問題。 這些類必須有一個工廠對象加以控制。
雖然它們在某些方面很像,但是實際上卻是不同的東西,單例模式的目的是限制建立多個對象,避免沖突,比如使用資料庫連接配接池。而享元模式享元模式的目的是共享,避免多次建立耗費資源,比如使用String類。
Java進階篇 設計模式之十四 ----- 總結篇
主要是通過一個類代表另一個類的功能。通常,我們建立具有現有對象的對象,以便向外界提供功能接口。

代理模式主要由這三個角色組成,抽象角色、代理角色和真實角色。

抽象角色:通過接口或抽象類聲明真實角色實作的業務方法。

代理角色:實作抽象角色,是真實角色的代理,通過真實角色的業務邏輯方法來實作抽象方法,并可以附加自己的操作。

真實角色:實作抽象角色,定義真實角色所要實作的業務邏輯,供代理角色調用。

代理模式又分為靜态代理、動态代理。

靜态代理是由程式員建立或工具生成代理類的源碼,再編譯代理類。所謂靜态也就是在程式運作前就已經存在代理類的位元組碼檔案,代理類和委托類的關系在運作前就确定了。

動态代理是在實作階段不用關心代理類,而在運作階段才指定哪一個對象。可以使用JDK中<code>java.lang.reflect</code>來進行開發。

1、遠端代理。 2、虛拟代理。 3、Copy-on-Write 代理。 4、保護(Protect or Access)代理。 5、Cache代理。 6、防火牆(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(SmartReference)代理。
1、職責清晰。 2、高擴充性。 3、智能化。
1、由于在用戶端和真實主題之間增加了代理對象,是以有些類型的代理模式可能會造成請求的處理速度變慢。 2、實作代理模式需要額外的工作,有些代理模式的實作非常複雜。
和擴充卡模式的差別:擴充卡模式主要改變所考慮對象的接口,而代理模式不能改變所代理類的接口。 和裝飾器模式的差別:裝飾器模式為了增強功能,而代理模式是為了加以控制。
Java進階篇 設計模式之十四 ----- 總結篇
責任鍊模式顧名思義,就是為請求建立了一個接收者對象的鍊。這種模式給予請求的類型,對請求的發送者和接收者進行解耦。這種類型的設計模式屬于行為型模式。在這種模式中,通常每個接收者都包含對另一個接收者的引用。如果一個對象不能處理該請求,那麼它會把相同的請求傳給下一個接收者,依此類推。 簡單的了解的話就是進行層級處理。

責任鍊模式主要由這三個角色組成,請求接收者接口(Handler)、請求實作者類(ConcreteHandler)和請求發送者(Client)。

請求接收者接口:定義可以處理用戶端請求事項的接口,包含“可連結下一個同樣能處理請求”的對象引用。

請求實作者類:實作請求處理接口,并判斷對象本身是否能夠處理本次請求,如果不能完成請求,則交由後繼者來處理。

請求發送者:将請求發送給第一個接收者對象,并等待請求的回複。

需要動态指定處理某一組請求時,在不确定接受者的的情況下,向多個對象發送請求時。
耦合度低,請求者和執行者并沒有必然的聯系; 靈活度高,可以通過内部成員來進行更改它們執行的次序; 擴充性好,Handler的子類擴充非常友善。
會在某程度上降低程式的性能,設定不當的話可能會出現循環調用。 在鍊過長時,會降低代碼的閱讀性以及增加代碼的複雜度。
雖然責任鍊模式很靈活,但是犧牲的是一定的性能,因為責任鍊模式是層級處理,在處理資料的有一定的延遲,所是以需要低延遲的情況下,不推薦使用責任鍊模式。
Java進階篇 設計模式之十四 ----- 總結篇
指令模式顧名思義,是一種資料驅動的設計模式,它屬于行為型模式。請求以指令的形式包裹在對象中,并傳給調用對象。調用對象尋找可以處理該指令的合适的對象,并把該指令傳給相應的對象,該對象執行指令。 也就是将一個請求封裝成一個對象,進而可以用不同的請求對客戶進行參數化。

指令模式主要由這三個角色組成,指令對象(command)、指令執行對象(received)和指令請求對象(invoker)。

指令對象:通過接口或抽象類聲明實作的方法。

指令執行對象:實作指令對象的方法,并将一個接收者和動作進行綁定,調用接收者相應的操作。

指令請求對象:用于執行這個請求,可以動态的對指令進行控制。

如果在有類似<code>指令</code>需要指定的,就可以用指令模式,比如記錄日志、撤銷操作指令等。
擴充性好,Command的子類可以非常容易地擴充。
如果指令過多的話,會增加系統的複雜度 。
Java進階篇 設計模式之十四 ----- 總結篇
解釋器模式顧名思義,就是對某事物進行解釋。給定一個語言之後,解釋器模式可以定義出其文法的一種表示,并同時提供一個解釋器。用戶端可以使用這個解釋器來解釋這個語言中的句子。 解釋器模式其實就是對某事物進行解釋。

解釋器模式主要由這四個角色組成,抽象表達式(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。 有重複的問題的時候。
擴充性好,子類擴充非常友善。 實作簡單。
可使用的場景比較少; 類過多的話,會使代碼臃腫,難以維護;
Java進階篇 設計模式之十四 ----- 總結篇
疊代器模式用于順序通路集合對象的元素,不需要知道集合對象的底層表示,屬于行為型模式。 它提供一種方法順序通路一個聚合對象中各個元素, 而又無須暴露該對象的内部表示。

疊代器模式主要由這四個角色組成,疊代器角色(Iterator)、具體疊代器角色(Concrete Iterator)、容器角色(Container)和具體容器角色(Concrete Container)。

疊代器角色(Iterator):通過接口或抽象類聲明實作的方法。

具體疊代器角色(Concrete Iterator):具體疊代器角色要實作疊代器接口,并要記錄周遊中的目前位置。

容器角色(Container):容器角色負責提供建立具體疊代器角色的接口。

具體容器角色(Concrete Container):具體容器角色實作建立具體疊代器角色的接口——這個具體疊代器角色于該容器的結構相關。

需要為聚合對象提供周遊的功能的時候。
靈活度高,可以通過不同的方式周遊對象; 擴充性好,可以很友善的增加新的聚合類和疊代器類而不用修改之前的代碼。
由于疊代器模式将存儲資料和周遊資料的職責分離,增加新的聚合類需要對應增加新的疊代器類,類的個數成對增加,這在一定程度上增加了系統的複雜性。
Java進階篇 設計模式之十四 ----- 總結篇
通路者模式(VisitorPattern),顧名思義使用了這個模式後就可以在不修改已有程式結構的前提下,通過添加額外的通路者來完成對已有代碼功能的提升,它屬于行為模式。通路者模式的目的是封裝一些施加于某種資料結構元素之上的操作。一旦這些操作需要修改的話,接受這個操作的資料結構則可以保持不變。 其主要目的是将資料結構與資料操作分離。

通路者模式主要由這五個角色組成,抽象通路者(Visitor)、具體通路者(ConcreteVisitor)、抽象節點(Node)、具體節點(ConcreteNode)和結構對象(ObjectStructure)。

抽象通路者(Visitor)角色:聲明了一個或者多個方法操作,形成所有的具體通路者角色必須實作的接口。

具體通路者(ConcreteVisitor)角色:實作抽象通路者所聲明的接口,也就是抽象通路者所聲明的各個通路操作。

抽象節點(Node)角色:聲明一個接受操作,接受一個通路者對象作為一個參數。

具體節點(ConcreteNode)角色:實作了抽象節點所規定的接受操作。

結構對象(ObjectStructure)角色:有如下的責任,可以周遊結構中的所有元素。

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

通路者模式優點:

擴充性好,可以在不修改對象結構中的元素的情況下,為對象結構中的元素添加新的功能; 符合單一職責原則,通過通路者将無關的行為分離,使職責單一;

通路者模式缺點:

違反了迪米特原則,因為具體元素對通路者公布細節; 違反了依賴倒置原則,依賴了具體類,沒有依賴抽象; 對象結構變化困難,若對象結構發生了改變,通路者的接口和通路者的實作也都要發生相應的改變;
Java進階篇 設計模式之十四 ----- 總結篇
中介者模式(Mediator Pattern),定義了一個中介對象來封裝一系列對象之間的互動關系。中介者使各個對象之間不需要顯式地互相引用,進而使耦合性降低,而且可以獨立地改變它們之間的互動行為,屬于行為型模式。 其主要的目的是用來降低多個對象和類之間的通信複雜性。

中介者模式主要由這四個角色組成, 抽象中介者(Mediator)、具體中介者(ConcreteMediator)、 抽象同僚類(Colleague)和具體同僚類(ConcreteColleague) 。

抽象中介者(Mediator): 定義了同僚對象到中介者對象之間的接口。

具體中介者(ConcreteMediator): 實作抽象中介者的方法,它需要知道所有的具體同僚類,同時需要從具體的同僚類那裡接收資訊,并且向具體的同僚類發送資訊。

抽象同僚類(Colleague): 定義了中介者對象的接口,它隻知道中介者而不知道其他的同僚對象。

具體同僚類(ConcreteColleague) : 每個具體同僚類都隻需要知道自己的行為即可,但是他們都需要認識中介者。

通過一個中間類來封裝多個類中的行為,而又不想生成太多的子類。
靈活性高,因為将同僚類進行了解耦,使其不必有關聯性; 降低了類的複雜度,将一對多轉化成了一對一;
中介者使用過多,會使系統變得複雜難以維護;
若不明确各個類的職責,那麼就不要進行使用!

和外觀模式、代理模式比較

中介者模式和外觀模式、代理模式比較類似,但是又有不同。 和外觀模式比較,中介者模式中,同僚類必須依賴與中介者,中介者也知道同僚類;但是外觀模式中,子系統是不需要知道外觀類的存在,并且子系統是可以脫離外觀模式的。 和代理模式,代理模式的核心就是代理作用,主要還是對原先的類進行擴充或增加控制,比如進行權限控制;而中介者模式主要目的是為了減少對象之前的耦合,也就是同僚類直接互相獨立,互不影響。
Java進階篇 設計模式之十四 ----- 總結篇
政策模式(Strategy Pattern)屬于對象的行為模式。其用意是針對一組算法,将每一個算法封裝到具有共同接口的獨立的類中,進而使得它們可以互相替換。政策模式使得算法可以在不影響到用戶端的情況下發生變化。 其主要目的是通過定義相似的算法,替換if else 語句寫法,并且可以随時互相替換。

政策模式主要由這三個角色組成,環境角色(Context)、抽象政策角色(Strategy)和具體政策角色(ConcreteStrategy)。

環境角色(Context):持有一個政策類的引用,提供給用戶端使用。

抽象政策角色(Strategy):這是一個抽象角色,通常由一個接口或抽象類實作。此角色給出所有的具體政策類所需的接口。

具體政策角色(ConcreteStrategy):包裝了相關的算法或行為。

如果在一個系統裡面有許多類,它們之間的差別僅在于它們的行為,那麼使用政策模式可以動态地讓一個對象在許多行為中選擇一種行為; 一個系統需要動态地在幾種算法中選擇一種; 如果一個對象有很多的行為,如果不用恰當的模式,這些行為就隻好使用多重的條件選擇語句來實作;
擴充性好,可以在不修改對象結構的情況下,為新的算法進行添加新的類進行實作; 靈活性好,可以對算法進行自由切換;
使用政策類變多,會增加系統的複雜度。; 用戶端必須知道所有的政策類才能進行調用;
Java進階篇 設計模式之十四 ----- 總結篇
模闆模式(Template Pattern)中,一個抽象類公開定義了執行它的方法的方式/模闆。它的子類可以按需要重寫方法實作,但調用将以抽象類中定義的方式進行。 這種類型的設計模式屬于行為型模式。定義一個操作中的算法的骨架,而将一些步驟延遲到子類中。 模闆模式,其主要的的思想就是做一個模闆,提供給用戶端進行調用。

模闆模式主要由抽象模闆(Abstract Template)角色和具體模闆(Concrete Template)角色組成。

抽象模闆(Abstract Template): 定義了一個或多個抽象操作,以便讓子類實作。這些抽象操作叫做基本操作,它們是一個頂級邏輯的組成步驟;定義并實作了一個模闆方法。這個模闆方法一般是一個具體方法,它給出了一個頂級邏輯的骨架,而邏輯的組成步驟在相應的抽象操作中,推遲到子類實作。頂級邏輯也有可能調用一些具體方法。

具體模闆(Concrete Template): 實作父類所定義的一個或多個抽象方法,它們是一個頂級邏輯的組成步驟;每一個抽象模闆角色都可以有任意多個具體模闆角色與之對應,而每一個具體模闆角色都可以給出這些抽象方法(也就是頂級邏輯的組成步驟)的不同實作,進而使得頂級邏輯的實作各不相同。

有多個子類共有邏輯相同的方法; 重要的、複雜的方法,可以考慮作為模闆方法。
擴充性好,對不變的代碼進行封裝,對可變的進行擴充; 可維護性好,因為将公共代碼進行了提取,使用的時候直接調用即可;
因為每一個不同的實作都需要一個子類來實作,導緻類的個數增加,會使系統變得複雜;
為防止惡意操作,一般模闆方法都加上 final 關鍵詞!
Java進階篇 設計模式之十四 ----- 總結篇
備忘錄模式(Memento Pattern)用于儲存一個對象的某個狀态,以便在适當的時候恢複對象,該模式屬于行為型模式。 其主要目的是在不破壞封裝性的前提下,捕獲一個對象的内部狀态,并在該對象之外儲存這個狀态。 其主要的的思想就是備份。

備忘錄模式主要由這三個角色組成,備忘錄角色(Memento)、發起人角色(Originator)和負責人(Caretaker)角色。

備忘錄(Memento):主要的功能是包含要被恢複的對象的狀态。

發起人(Originator):在建立的時候,會在備忘錄對象中存儲狀态。

負責人(Caretaker):主要是負責從備忘錄對象中恢複對象的狀态。

需要儲存/恢複資料的相關狀态場景;

優點

給使用者提供了一種可以恢複狀态的機制,可以使使用者能夠比較友善地回到某個曆史的狀态; 實作了資訊的封裝,使得使用者不需要關心狀态的儲存細節;
非常的消耗資源;
Java進階篇 設計模式之十四 ----- 總結篇
狀态模式(State Pattern)屬于行為型模式,其狀态的對象和一個行為随着狀态對象改變而改變。 其主要目的解決的是當控制一個對象狀态轉換的條件表達式過于複雜是的情況。把狀态的判斷邏輯轉移到表示不同狀态一系列類中,可以把複雜的判斷簡單化。 主要的的思想就是提供一種狀态,提供給用戶端進行調用。

狀态模式主要由環境角色(Context)、 抽象狀态(State)和具體狀态(Concrete State)組成。

環境角色(Context): 它定義了客戶程式需要的接口并維護一個具體狀态角色的執行個體,将與狀态相關的操作委托給目前的具體狀态對象來處理。

抽象狀态角色(State): 定義一個接口以封裝使用上下文環境的的一個特定狀态相關的行為。

具體狀态角色(Concrete State):實作抽象狀态定義的接口。

行為随狀态改變而改變的場景; 條件、分支語句的代替者。
擴充性好,将和狀态有關的行為放到一起,增加新的的狀态,隻需要改變對象狀态即可改變對象的行為即可; 複用性好,讓多個環境對象共享一個狀态對象,進而減少系統中對象的個數;
使用狀态模式會增加系統類和對象的個數,并且該模式的結構與實作都較為複雜,如果使用不當将導緻程式結構和代碼的混亂; 狀态模式對"開閉原則"的支援并不太好,對于可以切換狀态的狀态模式,增加新的狀态類需要修改那些負責狀态轉換的源代碼,否則無法切換到新增狀态,而且修改某個狀态類的行為也需修改對應類的源代碼。
在行為受狀态限制的時候使用狀态模式,而且狀态不超過5個。

和政策模式比較

在學習狀态模式的時候,很容易和政策模式搞混,因為它們實在是太像了,很難區分,在查閱一番資料之後,整理了如下的相同點和差別點。

相同點:

它們很容易添加新的狀态或政策,而且不需要修改使用它們的Context對象。

它們都符合OCP原則,在狀态模式和政策模式中,Context對象對修改是關閉的,添加新的狀态或政策,都不需要修改Context。

它們都會初始化。

它們都依賴子類去實作相關行為。

差別點

狀态模式的行為是平行性的,不可互相替換的;

而政策模式的行為是平等性的,是可以互相替換的。

最重要的一個不同之處是,政策模式的改變由用戶端完成;

而狀态模式的改變,由環境角色或狀态自己.

Java進階篇 設計模式之十四 ----- 總結篇
觀察者模式又叫釋出-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式。觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀态上發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。。 其主要目的是定義對象間的一種一對多的依賴關系,當一個對象的狀态發生改變時,所有依賴于它的對象都得到通知并被自動更新。

觀察者模式主要由這四個角色組成,抽象主題角色(Subject)、具體主題角色(ConcreteSubject)、抽象觀察者角色(Observer)和具體觀察者角色(ConcreteObserver)。

抽象主題角色(Subject):它把所有觀察者對象的引用儲存到一個聚集裡,每個主題都可以有任何數量的觀察者。抽象主題提供一個接口,可以增加和删除觀察者對象。

具體主題角色(ConcreteSubject):将有關狀态存入具體觀察者對象;在具體主題内部狀态改變時,給所有登記過的觀察者發出通知。

抽象觀察者角色(Observer):主要是負責從備忘錄對象中恢複對象的狀态。

需要關聯行為的場景; 事件需要建立一個觸發鍊的場景,比如監控; 跨系統的消息交換場景,比如消息隊列、事件總線的處理機制。
解除耦合,讓耦合的雙方都依賴于抽象,進而使得各自的變換都不會影響另一邊的變換。
如果一個被觀察者對象有很多的直接和間接的觀察者的話,将所有的觀察者都通知到會花費很多時間; 如果在觀察者和觀察目标之間有循環依賴的話,觀察目标會觸發它們之間進行循環調用,可能導緻系統崩潰; 觀察者模式沒有相應的機制讓觀察者知道所觀察的目标對象是怎麼發生變化的,而僅僅隻是知道觀察目标發生了變化。
如果順序執行,某一觀察者錯誤會導緻系統卡殼,建議采用異步方式。
Java進階篇 設計模式之十四 ----- 總結篇
空對象模式(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

如果你對生活感覺到了絕望,請不要氣餒。因為這樣隻會讓你更加絕望!

所謂的希望往往都是在絕望中萌發的,是以,請不要放棄希望!

繼續閱讀