續(xù) 設計模式思考 II
思考方式:
1.這種模式怎么理解?(盡量簡單易懂)
2.類圖怎樣畫溉苛?(代碼怎樣寫)
3.舉個栗子弄诲?(使用場景)
4.使用這種模式有什么優(yōu)缺點?(遵循什么原則)
行為型模式
14.觀察者模式(Observer)
(1)理解
對象間的一種一對多的依賴關系齐遵,當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新敢茁。
(2)類圖
(3)栗子
Android的點擊事件onClickListener留美;涉及到數(shù)據(jù)狀態(tài)發(fā)生變化需要通知的情況下伸刃,如郵件訂閱和RSS訂閱逢倍,后續(xù)有更新,會及時通知碉哑;
(4)優(yōu)缺點
優(yōu):目標和觀察者間的抽象耦合亮蒋;支持廣播通信
15.模板方法模式(Template Method)
(1)理解
一個操作中的算法的骨架,而將一些步驟延遲到子類中贮尖,模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。
(2)類圖
制造咖啡和茶的模板方法:
(3)栗子
Android的View的draw方法
適用場景:
a.算法或操作遵循相似的邏輯
b.重構時(把相同的代碼抽取到父類中)
c.重要趁怔、復雜的算法湿硝,核心算法設計為模板算法
(4)優(yōu)缺點
優(yōu):封裝性好、復用性好润努、屏蔽細節(jié)关斜、便于維護
缺:單繼承
16.命令模式(Command)
(1)理解
將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進行參數(shù)化铺浇,對請求排隊或記錄請求日志痢畜,以及支持可撤銷的操作随抠。
(2)類圖
舉個例子裁着,司令員下令讓士兵去干件事情,從整個事情的角度來考慮拱她,司令員的作用是二驰,發(fā)出口令,口令經(jīng)過傳遞秉沼,傳到了士兵耳朵里桶雀,士兵去執(zhí)行。這個過程好在唬复,三者相互解耦矗积,任何一方都不用去依賴其他人,只需要做好自己的事兒就行敞咧,司令員要的是結果棘捣,不會去關注到底士兵是怎么實現(xiàn)的。
Invoker是調(diào)用者(司令員)休建,Receiver是被調(diào)用者(士兵)乍恐,MyCommand是命令评疗,實現(xiàn)了Command接口,持有接收對象茵烈,通過以下代碼實現(xiàn)調(diào)用:
Receiver receiver = new Receiver();
Command cmd = new MyCommand(receiver);
Invoker invoker = new Invoker(cmd);
invoker.action();
(3)栗子
java平臺的事件機制百匆,Java Web的Struts,涉及一種將請求和呈現(xiàn)分離的技術呜投。
(4)優(yōu)缺點
優(yōu): 解耦了命令請求者和接受者之間聯(lián)系加匈。請求者調(diào)用一個命令,接受者接受請求并執(zhí)行相應的動作仑荐,因為使用Command模式解耦雕拼,請求者無需知道接受者任何接口。
缺: 造成出現(xiàn)過多的具體命令類释漆。
17.狀態(tài)模式(State)
(1)理解
當對象的狀態(tài)改變時悲没,同時改變其行為。就QQ來說男图,有幾種狀態(tài),在線甜橱、隱身逊笆、忙碌等,每個狀態(tài)對應不同的操作岂傲,而且你的好友也能看到你的狀態(tài)难裆,所以,狀態(tài)模式就兩點:a.可以通過改變狀態(tài)來獲得不同的行為镊掖。b.你的好友能同時看到你的變化乃戈。
(2)類圖
(3)栗子
適用于有多種狀態(tài),每種狀態(tài)又有不同操作的情況亩进,如權限控制症虑。
(4)優(yōu)缺點
優(yōu):狀態(tài)自動切換并傳播,不需要再改動標識
注:State狀態(tài)模式和Proxy代理模式都為客戶端程序提供了一個目標程序代理归薛,真正的目標程序被代理所隱藏谍憔,當客戶端程序調(diào)用目標程序時,首先將調(diào)用請求發(fā)送給代理主籍,代理才真正調(diào)用目標程序习贫,但是Proxy代理模式和State狀態(tài)模式有如下區(qū)別:
a.Proxy代理模式中被調(diào)用的目標程序只有一個,而State狀態(tài)模式中被調(diào)用的目標程序有多個千元。
b.Proxy代理模式的目的是控制客戶端對目標程序的訪問苫昌,而State狀態(tài)模式是為了根據(jù)條件動態(tài)改變目標程序。
18.職責鏈模式(Chain of Responsibility)
(1)理解
有多個對象幸海,每個對象持有對下一個對象的引用祟身,這樣就會形成一條鏈屋厘,請求在這條鏈上傳遞,直到某一對象決定處理該請求月而。但是發(fā)出者并不清楚到底最終那個對象會處理該請求汗洒,所以,責任鏈模式可以實現(xiàn)父款,在隱瞞客戶端的情況下溢谤,對系統(tǒng)進行動態(tài)的調(diào)整。
(2)類圖
執(zhí)行以下代碼:
MyHandler h1=new MyHandler("h1");
MyHandler h2=new MyHandler("h2");
MyHandler h3=new MyHandler("h3");
h1.setHandler(h2);
h2.setHandler(h3);
h1.operator();
/*結果:
h1deal...
h2deal...
h3deal...
*/
(3)栗子
Java中Chain of Responsibility的兩個應用例子:
a.Java的異常處理機制憨攒,當程序中發(fā)生異常時世杀,try-catch會比較所捕捉的異常是否符合異常類型,如果符合就執(zhí)行所設定的處理肝集,如果都沒有比對到適當?shù)漠惓U鞍樱蜁惓G出try-catch區(qū)塊之外。
b.Struts1.x中的filter過濾器鏈杏瞻,Struts2.x中攔截器鏈等等所刀,將HTTP請求處理中的字符編碼轉換,加密/解密等常用功能分別作為一個個的請求處理器捞挥,接收到客戶端請求時對其進行處理浮创,同時在向客戶端返回服務端響應時也使用這些處理器進行處理。
(4)優(yōu)缺點
優(yōu):責任鏈模式可以實現(xiàn)砌函,在隱瞞客戶端的情況下斩披,對系統(tǒng)進行動態(tài)的調(diào)整。
19.解釋器模式(Interpreter)
(1)理解
給定一個語言讹俊,定義其文法的一種表示垦沉,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子仍劈。一般主要應用在OOP開發(fā)中的編譯器的開發(fā)中厕倍,所以適用面比較窄。
(2)類圖
(3)栗子
各種各樣的解釋器耳奕,如正則表達式等的解釋器等绑青。
(4)優(yōu)缺點
優(yōu): 可以比較方便的修改和擴展文法規(guī)則。
缺:針對每一個規(guī)則都定義了一個類屋群,所以如果一個文法的規(guī)則比較多闸婴,那對于文法的維護工作也會變得非常困難。
20.中介者模式(Mediator)
(1)理解
用一個中介對象來封裝一系列的對象交互芍躏,中介者使各對象不需要顯式地相互引用邪乍,從而使其耦合松散,而且可以獨立地改變它們之間的交互。中介者模式又稱為調(diào)停者模式庇楞。
(2)類圖
User類統(tǒng)一接口榜配,User1和User2分別是不同的對象,二者之間有關聯(lián)吕晌,如果不采用中介者模式蛋褥,則需要二者相互持有引用,這樣二者的耦合度很高睛驳,為了解耦烙心,引入了Mediator類,提供統(tǒng)一接口乏沸,MyMediator為其實現(xiàn)類淫茵,里面持有User1和User2的實例,用來實現(xiàn)對User1和User2的控制蹬跃。這樣User1和User2兩個對象相互獨立匙瘪,他們只需要保持好和Mediator之間的關系就行,剩下的全由MyMediator類來維護蝶缀!詳細:22.中介者模式(Mediator)
(3)栗子
使用情形:在對象之間的交互操作非常多的情況下;每個對象的行為操作都可能依賴很多其他對象,修改一個對象的行為的同時可能會影響到很多其他對象的行為丹喻。
(4)優(yōu)缺點
優(yōu):清除了一系列對象之間復雜的耦合關系,并且中介者可以控制這一系列對象的行為扼劈,統(tǒng)一管理
缺:由于中介者負責著一系列對象的交互與控制驻啤,所以中介者的類會非常復雜,而且一旦中介者類無法正常工作荐吵,那么所有將行為委托給中介者的類都將會出現(xiàn)問題,所以在使用的時候還是要特別小心赊瞬。
21.訪問者模式(Visitor)
(1)理解
把數(shù)據(jù)結構和作用于結構上的操作解耦合(即分離對象數(shù)據(jù)結構與行為)先煎,使得操作集合可相對自由地演化。即在不修改已有程序結構的前提下巧涧,通過添加額外的“訪問者”來完成對已有代碼功能的提升薯蝎。
(2)類圖
(3)栗子
適用場景:如果我們想為一個現(xiàn)有的類增加新功能,不得不考慮幾個事情:新功能會不會與現(xiàn)有功能出現(xiàn)兼容性問題谤绳?以后會不會再需要添加占锯?如果類不允許修改代碼怎么辦?
面對這些問題缩筛,最好的解決方法就是使用訪問者模式消略,訪問者模式適用于數(shù)據(jù)結構相對穩(wěn)定的系統(tǒng),把數(shù)據(jù)結構和算法解耦瞎抛。
(4)優(yōu)缺點
優(yōu):增加操作很容易艺演,因為增加操作意味著增加新的訪問者。訪問者模式將有關行為集中到一個訪問者對象中,其改變不影響系統(tǒng)數(shù)據(jù)結構
缺:增加新的數(shù)據(jù)結構很困難胎撤。
22.策略模式(strategy)
(1)理解
定義一系列的算法晓殊,把它們一個個封裝起來,并且使它們可互相替換伤提。策略模式使得算法可獨立于使用它的客戶而變化巫俺。
(2)類圖
詳細見: 13策略模式(strategy)
(3)栗子
Android中的動畫;JDK的java.util.Comparator
適用場景:
a.許多相關的類僅僅是行為差異
b.運行時選取不同的算法變體
c.通過條件語句在多個分支中選取之一
(4)優(yōu)缺點
優(yōu):
a.使用組合肿男,使框架更加靈活
b.富有彈性介汹,可以較好的應對變化(開閉原則)
c.更好的代碼復用性(相對于繼承)
d.消除大量的條件語句
缺:
a.客戶代碼需要了解每個策略實現(xiàn)的細節(jié)
b.增加了對象的數(shù)目
注:State狀態(tài)模式和Strategy策略模式非常類似,但是有如下區(qū)別:
a.State狀態(tài)模式重點在于設定狀態(tài)變化次伶,根據(jù)狀態(tài)痴昧,返回相應的響應。
b.Strategy策略模式重點在于根據(jù)需求直接采用設定的策略冠王,即根據(jù)場景選擇合適的處理算法赶撰,而不需要改變狀態(tài)。
23.備忘錄模式(Memento)
(1)理解
在不破壞封裝性的前提下柱彻,捕獲一個對象的內(nèi)部狀態(tài)豪娜,并在該對象之外保存這個狀態(tài),這樣以后就可以將該對象恢復到先前保存的狀態(tài)哟楷。
(2)類圖
組織者瘤载,把原發(fā)器的狀態(tài)State(全部或者部分狀態(tài),一般是變量的值)卖擅,通過CreateMemento()方法保存起來鸣奔,繼續(xù)運行后,等待合適的時機惩阶,在通過SetMemento()方法可以再次恢復到之前的狀態(tài)挎狸。在這個過程中,我們并沒有對這些狀態(tài)做任何的訪問和設置断楷,實際上這些狀態(tài)都是私有的锨匆,對外是禁止訪問的,我們只是通過Memento對象的兩個最簡單的方法就達到了這個效果冬筒。Memento經(jīng)常寫成Originator的內(nèi)部類恐锣。詳細:Memento設計模式
(3)栗子
Android的Canvas的save(),restore();
適用于文字編輯軟件/IDE集成開發(fā)環(huán)境中的撤銷和恢復操作舞痰。
(4)優(yōu)缺點
優(yōu):
a.保持封裝邊界土榴,把很復雜的原發(fā)器的內(nèi)部信息對外部其他對象隱藏起來。
b.簡化的原發(fā)器匀奏,把狀態(tài)操作無形中轉化到客戶手里鞭衩,簡化了原發(fā)器的某些實現(xiàn)学搜。
24.迭代器模式(Iterator)
(1)理解
提供一種統(tǒng)一的方法訪問一個容器(container)對象中各個元素,而又不需暴露該對象的內(nèi)部細節(jié)论衍,迭代器模式是為容器而設計瑞佩。
(2)類圖
詳見: 16迭代子模式(Iterator)
(3)栗子
JDK中設計模式的應用:java.util.Iterator,java.util.Enumeration
(4)優(yōu)缺點
優(yōu):
a.實現(xiàn)功能分離坯台,簡化容器接口炬丸。讓容器只實現(xiàn)本身的基本功能,把迭代功能委讓給外部類實現(xiàn)蜒蕾,符合類的設計原則稠炬。
b.隱藏容器的實現(xiàn)細節(jié)。
c.為容器或其子容器提供了一個統(tǒng)一接口咪啡,一方面方便調(diào)用首启;另一方面使得調(diào)用者不必關注迭代器的實現(xiàn)細節(jié)。
d.可以為容器或其子容器實現(xiàn)不同的迭代方法或多個迭代方法撤摸。
持續(xù)更新毅桃,整理得不對的地方,還望指正准夷!
參考:
1.Java之美[從菜鳥到高手演變]之設計模式-終點
2.Android設計模式系列-謙虛天下
3.設計模式系列-Tony Chen
4.設計模式詳解-左瀟龍
5.設計模式UML類圖