組合模式(合成模式)
- 定義:
將對象合成樹形結(jié)構(gòu)以表示 整體-部分 的層次結(jié)構(gòu)棍掐,使得用戶對單個對象和組合對象的使用具有一致性贴铜。 - 自我理解:
用一系列的數(shù)據(jù)生成樹形結(jié)構(gòu)(整體-部分)腊敲。例如氓扛,給你公司的花名冊枯芬,現(xiàn)在要將花名冊以公司架構(gòu)的形式展示。即采郎,某部門千所,某部門下某些員工起便。 -
類圖:
- Component
抽象組合對象抖部,定義了所有組合對象的共有方法和屬性。 - Leaf
葉子對象循衰,類似于公司的基本員工整份,不管理任何人待错。 - Composite
樹枝結(jié)構(gòu)(branch),可以理解成管理層烈评。方便管理火俄,根節(jié)點(diǎn)也是它。其下有葉子對象讲冠。
Summary
- 優(yōu)點(diǎn)
1烛占、高層模塊調(diào)用簡單。
只要找到一個其中的一個節(jié)點(diǎn)沟启,可以找到root節(jié)點(diǎn)忆家。不必關(guān)心整體結(jié)構(gòu)。
2德迹、及誒單自由增加
想增加branch就增加branch芽卿,想增加leaf就增加leaf。 - 缺點(diǎn)
1胳搞、例如上面的leaf 和composite 是一個具體的實(shí)現(xiàn)類卸例,限制了接口的影響范圍称杨。 - 場景
1、維護(hù)和展示 部分-整體關(guān)系的場景筷转。eg:樹形菜單姑原,文件和文件夾。
2呜舒、從一個整體中能夠獨(dú)立出部分模塊或者功能的場景锭汛。
擴(kuò)展
組合模式有兩種不同的實(shí)現(xiàn):透明模式、安全模式袭蝗。
- 安全模式
上面的類圖就是安全模式唤殴。 -
透明模式
類圖
個人理解:
將樹枝和葉結(jié)構(gòu)統(tǒng)一成一個Component,然后根據(jù)其中的條件來判斷是葉子結(jié)構(gòu)還是樹枝結(jié)構(gòu)到腥。比如:getChild()朵逝,返回一個迭代器,如果迭代器是null或者數(shù)量為0乡范,那就說明這個結(jié)構(gòu)是一個葉子結(jié)構(gòu)配名。反之就是一個樹枝結(jié)構(gòu)。
觀察者模式(發(fā)布訂閱模型)
- 定義:定義對象間一種一對多的依賴關(guān)系晋辆,使得每當(dāng)一個對象改變狀態(tài)段誊,則所依賴于他的對象都會得到通知并被自動更新。
- 簡單理解:開關(guān) 與 燈的亮暗栈拖。燈是依賴于開關(guān)的连舍,當(dāng)開關(guān)的狀態(tài)發(fā)生改變,燈的亮暗也隨之發(fā)生改變涩哟。
-
類圖
- subject
被觀察者對象索赏,上面的開關(guān)。該類的要求是能夠動態(tài)的增減觀察者贴彼,同時能夠進(jìn)行通知潜腻。 - observer
觀察者,上面的燈器仗,根據(jù)被觀察者的行為融涣,做出相應(yīng)的操作。
Summary
- 優(yōu)點(diǎn)
1精钮、觀察者和被觀察者之間是抽象耦合
2威鹿、建立一套觸發(fā)機(jī)制 - 缺點(diǎn)
1、效率需要考慮轨香。 - 注意
1忽你、廣播鏈(被觀察者==》觀察者==》觀察者==》觀察者)這種情況的時候,依賴嚴(yán)重不建議這樣建立關(guān)系臂容。建議最多只有兩層關(guān)系(被觀察者==》觀察者==》觀察者)科雳。
2根蟹、異步處理問題,單一對多觀察的時候糟秘,考慮耗時简逮,可能需要開異步。這個時候需要考慮隊(duì)列以及線程安全尿赚∩⑹可以參考Message Queue,加深理解吼畏。 - 擴(kuò)展
1督赤、Observer 和 Observable Java中有現(xiàn)成的接口直接實(shí)現(xiàn)就可以工作了嘁灯。
門面模式(外觀模式)
- 定義:
要求一個子系統(tǒng)的外部與其內(nèi)部的通行必須通過一個統(tǒng)一的對象進(jìn)行泻蚊。門面模式提供一個高層次的接口,使得子系統(tǒng)更易于使用丑婿。 -
自我理解:
門面可以理解為一個封裝集合性雄,他定義的固定的對外接口,其內(nèi)部無論怎么變化羹奉,提供給外部的方法不能隨意變動秒旋。簡稱金玉其外敗絮其內(nèi)。
- Facade門面角色
子系統(tǒng)的封裝集合诀拭,沒有實(shí)際的業(yè)務(wù)邏輯迁筛。只是一個委托類。 - 子系統(tǒng)角色
可以同時有個或者多個耕挨,每個子系統(tǒng)類是一個類的集合细卧。子系統(tǒng)并不知道門面的存在。對于子系統(tǒng)而言筒占,門面僅僅是另一個客戶端而已贪庙。
Summary
- 優(yōu)點(diǎn)
1、減少了系統(tǒng)的相互耦合
因?yàn)閷⒆酉到y(tǒng)封裝了翰苫,所以外部訪問不會深入到子系統(tǒng)中的具體方法止邮,減少了耦合。
2奏窑、提高了靈活性
子系統(tǒng)隨便更改导披,只要保證提供門面的方法不變,上級依賴穩(wěn)定埃唯。
3盛卡、提高安全性
相當(dāng)于增加了一道防火墻,防止直接訪問子系統(tǒng)筑凫。 - 缺點(diǎn)
1滑沧、不符合開閉原則并村,對修改關(guān)閉,對擴(kuò)展開放滓技。門面出現(xiàn)問題之后哩牍,好像就玩不動了。這就是因?yàn)閷π薷年P(guān)閉原因令漂。 - 場景
1膝昆、為復(fù)雜模塊或者子系統(tǒng)提供訪問的接口
2、子系統(tǒng)相對獨(dú)立——外界對子系統(tǒng)的訪問只要黑箱操作即可
3叠必、預(yù)防低水平人員帶來的風(fēng)險荚孵,即開發(fā)模塊化,模塊間依賴單一纬朝,別人水平低不會影響到你(其實(shí)你水平更低)收叶。 - 注意
1、一個子系統(tǒng)可以有多個門面
2共苛、(重點(diǎn))門面不參與子系統(tǒng)內(nèi)的業(yè)務(wù)邏輯
就是門面中的方法不處理業(yè)務(wù)邏輯判没。
eg:
“public class Facade {
//被委托的對象
private ClassA a = new ClassA();
private ClassB b = new ClassB();
private ClassC c = new ClassC();
//提供給外部訪問的方法
public void methodA(){
this.a.doSomethingA();
}
public void methodB(){
this.b.doSomethingB();
}
public void methodC(){
this.a.doSomethingA();
this.c.doSomethingC();
}
}”
這種情況下,正確的做法是將A隅茎、C進(jìn)行一次封裝澄峰,生成新類,同事生成新方法辟犀。如下
“public class Context {
//委托處理
private ClassA a = new ClassA();
private ClassC c = new ClassC();
//復(fù)雜的計算
public void complexMethod(){
this.a.doSomethingA();
this.c.doSomethingC();
}
}”
“public class Facade {
//被委托的對象
private ClassA a = new ClassA();
private ClassB b = new ClassB();
private Context context = new Context();
//提供給外部訪問的方法
public void methodA(){
this.a.doSomethingA();
}
public void methodB(){
this.b.doSomethingB();
}
public void methodC(){
this.context.complexMethod();
}
}”
蛋疼是蛋疼俏竞,設(shè)計思想就是這樣的。
備忘錄模式
- 定義
在不破壞封裝性的前提下堂竟,捕獲一個對象的內(nèi)部狀態(tài)魂毁,并在改對象之外保存這個狀態(tài)。這樣以后就可以將該對象恢復(fù)到原先保存的狀態(tài)跃捣。 - 自我理解
打單機(jī)游戲的時候漱牵,經(jīng)常用到的SL大法(Save-Load)。簡單來說疚漆,將某一個狀態(tài)保存酣胀,方便歷史恢復(fù)。 -
類圖
- Originator
數(shù)據(jù)源 - Memento
負(fù)責(zé)存儲數(shù)據(jù)源的數(shù)據(jù)狀態(tài)娶聘,生成備忘錄闻镶。 - Caretaker
對備忘錄進(jìn)行管理的類。
拓展
-
Clone方式的備忘錄
記得之前的原型模式中用到的Clone丸升,將當(dāng)前的類進(jìn)行Clone產(chǎn)生一個相同狀態(tài)的類铆农。
類圖
操作
讓originator 實(shí)現(xiàn)Clone接口,然后生成備忘錄的時候狡耻,直接返回克隆對象給備忘錄管理類墩剖。
注意:采用的是Clone接口猴凹,所以還是存在Clone 的弊端,如果成員變量有非原始數(shù)據(jù)類型的岭皂,需要進(jìn)行深度拷貝郊霎。
-
多狀態(tài)備忘錄模式
背景
當(dāng)Originator屬性成員過多的時候,在手動賦值還原的話容易出錯爷绘,而且也是機(jī)械重復(fù)操作過多书劝。為了解決這個問題,需要對bean的描述進(jìn)行解析土至。
類圖
新增一個BeanUtil類進(jìn)行屬性數(shù)據(jù)的提取和還原购对。
注意
1、通過bean描述提取屬性的時候陶因,讀取的時候是根據(jù)方法名開頭以get來過濾的骡苞,所以,寫代碼的時候需要住坑赡,反之出現(xiàn)重復(fù)調(diào)用烙如,行成死循環(huán)么抗。
2毅否、成員變量中,保存的是引用地址蝇刀,所以會出現(xiàn)類似深度拷貝螟加,和淺拷貝的問題。對于像list的非原始數(shù)據(jù)額類型吞琐,需要單獨(dú)clone 賦值捆探。
= 多備份的備忘錄
背景
歷史備份不僅可以有一份備份,也可以有多份備份站粟。所以這種情況下黍图,就需要使用多備份的備忘錄。核心是通過Hashmap 生成關(guān)鍵字對應(yīng)的備忘錄奴烙,進(jìn)行管理調(diào)用還原助被。
類圖
優(yōu)化
讓備忘錄實(shí)現(xiàn)一個空接口,之后以空接口作為上層代碼的引用切诀。反之?dāng)?shù)據(jù)暴露揩环。
以上四種實(shí)現(xiàn)相關(guān)代碼==》個人github
Summary
- 應(yīng)用場景
需要保存和恢復(fù)的應(yīng)用場景。入歷史回滾幅虑。
需要監(jiān)控副本場景
jdbc(數(shù)據(jù)庫調(diào)用)的本質(zhì)就是備忘錄丰滑。
訪問者模式
- 定義:
封裝一些作用于某種數(shù)據(jù)結(jié)構(gòu)中的各元素操作,可以在不改變數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新操作倒庵。 -
自我理解
留一個接口出來褒墨,用于擴(kuò)展數(shù)該數(shù)據(jù)結(jié)構(gòu)的元素操作炫刷。
- visitor
抽象訪問者,抽象接口或者抽象類郁妈,聲明訪問哪些元素柬唯。 - ConcreteVisitor
具體訪問者實(shí)現(xiàn)類。 - Element
抽象元素圃庭,聲明接受哪一類訪問者訪問锄奢,程序上是通過accept方法中的參數(shù)來定義。 - ConcreteElement
具體元素剧腻,被操作的對象 - ObjectStruture
元素產(chǎn)生者拘央,可以理解為元素的容器或者元素管理者。
Summary
- 優(yōu)點(diǎn)
符合單一職責(zé)原則
擴(kuò)張性優(yōu)秀书在、靈活性高 - 缺點(diǎn)
訪問者能夠關(guān)注到被訪問者的內(nèi)部細(xì)節(jié)灰伟,跟迪米特法則相違背。
違背依賴倒置原則儒旬,因?yàn)樵L問者所依賴的 是具體的實(shí)現(xiàn)類而不是一個接口或者抽象類栏账。 - 場景
1、需要對一個對象結(jié)構(gòu)中的對象進(jìn)行很多不同并且不相關(guān)的操作栈源,而你想避免讓這些操作污染這些對象的類
2挡爵、使用迭代器遍歷對象,這個時候還需要做個性操作甚垦,這種情況就可以使用訪問者模式茶鹃。 - 擴(kuò)展
1、統(tǒng)計功能艰亮,對需要計數(shù)操作的遍歷的一種拖拽闭翩。
2、多訪問者迄埃,添加多個訪問者疗韵。
3、雙分派
狀態(tài)模式
-
引子
從電梯的狀態(tài)操作開始說起侄非,電梯有四種狀態(tài)蕉汪,停止、運(yùn)行彩库、開門肤无、關(guān)門。同一種狀態(tài)下有多中操作骇钦,但是這些操作是否被允許視具體情況而定宛渐。
這種情況可以用根據(jù)每種情況然后用switch來搞定,如果狀態(tài)很多的情況,可能代碼量很大窥翩,而且邏輯很能比較混亂业岁。這里就引出出了狀態(tài)模式。平時寫代碼還是喜歡直接上switch寇蚊,還是覺得用模式麻煩笔时。
定義
當(dāng)一個對象內(nèi)在狀態(tài)改變時允許其改變行為,這個對象看起來像改變了其類仗岸。-
自我理解
還是看上面的引子吧允耿,定義說得自己都云里霧里的。
State ——抽象狀態(tài)角色
負(fù)責(zé)對象狀態(tài)定義扒怖,并且封裝環(huán)境角色以實(shí)現(xiàn)狀態(tài)切換较锡。ConcreteState ——具體狀態(tài)角色
兩個職責(zé):
1、狀態(tài)變更
2盗痒、行為管理Context ——環(huán)境角色
定義客戶端需要的接口蚂蕴,并且負(fù)責(zé)具體狀態(tài)的切換。
Summary
優(yōu)點(diǎn)
結(jié)構(gòu)清晰俯邓,清晰是清晰覺得麻煩好多
遵循設(shè)計原則(廢話)
封裝性非常好缺點(diǎn)
當(dāng)狀態(tài)多骡楼、方法多的時候類非常龐大。場景
1稽鞭、行為會隨著狀態(tài)改變而改變的場景
2鸟整、條件、分支判斷語句的替代者注意
狀態(tài)數(shù)量最好不要超過5個川慌。