設(shè)計模式之禪——設(shè)計模式(三)

組合模式(合成模式)
  • 定義:
    將對象合成樹形結(jié)構(gòu)以表示 整體-部分 的層次結(jié)構(gòu)棍掐,使得用戶對單個對象和組合對象的使用具有一致性贴铜。
  • 自我理解:
    用一系列的數(shù)據(jù)生成樹形結(jié)構(gòu)(整體-部分)腊敲。例如氓扛,給你公司的花名冊枯芬,現(xiàn)在要將花名冊以公司架構(gòu)的形式展示。即采郎,某部門千所,某部門下某些員工起便。
  • 類圖:


    image.png
  • 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):透明模式、安全模式袭蝗。

  • 安全模式
    上面的類圖就是安全模式唤殴。
  • 透明模式
    類圖


    image.png

    個人理解:
    將樹枝和葉結(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ā)生改變涩哟。
  • 類圖


    image.png
  • 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)。


    image.png

    image.png
  • 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ù)。
  • 類圖


    image.png
  • 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)的類铆农。
    類圖


    image.png

操作
讓originator 實(shí)現(xiàn)Clone接口,然后生成備忘錄的時候狡耻,直接返回克隆對象給備忘錄管理類墩剖。

注意:采用的是Clone接口猴凹,所以還是存在Clone 的弊端,如果成員變量有非原始數(shù)據(jù)類型的岭皂,需要進(jìn)行深度拷貝郊霎。

  • 多狀態(tài)備忘錄模式
    背景
    當(dāng)Originator屬性成員過多的時候,在手動賦值還原的話容易出錯爷绘,而且也是機(jī)械重復(fù)操作過多书劝。為了解決這個問題,需要對bean的描述進(jìn)行解析土至。
    類圖


    image.png

    新增一個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)用還原助被。
類圖


image.png

優(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)的元素操作炫刷。


    image.png
  • 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)下有多中操作骇钦,但是這些操作是否被允許視具體情況而定宛渐。


    image.png

這種情況可以用根據(jù)每種情況然后用switch來搞定,如果狀態(tài)很多的情況,可能代碼量很大窥翩,而且邏輯很能比較混亂业岁。這里就引出出了狀態(tài)模式。平時寫代碼還是喜歡直接上switch寇蚊,還是覺得用模式麻煩笔时。

  • 定義
    當(dāng)一個對象內(nèi)在狀態(tài)改變時允許其改變行為,這個對象看起來像改變了其類仗岸。

  • 自我理解
    還是看上面的引子吧允耿,定義說得自己都云里霧里的。


    image.png
  • 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個川慌。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吃嘿,一起剝皮案震驚了整個濱河市祠乃,隨后出現(xiàn)的幾起案子梦重,更是在濱河造成了極大的恐慌,老刑警劉巖亮瓷,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件琴拧,死亡現(xiàn)場離奇詭異,居然都是意外死亡嘱支,警方通過查閱死者的電腦和手機(jī)蚓胸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來除师,“玉大人沛膳,你說我怎么就攤上這事⊙淳郏” “怎么了锹安?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我叹哭,道長忍宋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任风罩,我火速辦了婚禮糠排,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘超升。我一直安慰自己入宦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布室琢。 她就那樣靜靜地躺著云石,像睡著了一般。 火紅的嫁衣襯著肌膚如雪研乒。 梳的紋絲不亂的頭發(fā)上汹忠,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機(jī)與錄音雹熬,去河邊找鬼宽菜。 笑死,一個胖子當(dāng)著我的面吹牛竿报,可吹牛的內(nèi)容都是我干的铅乡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼烈菌,長吁一口氣:“原來是場噩夢啊……” “哼阵幸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起芽世,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤挚赊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后济瓢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荠割,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年旺矾,在試婚紗的時候發(fā)現(xiàn)自己被綠了蔑鹦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡箕宙,死狀恐怖嚎朽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情柬帕,我是刑警寧澤哟忍,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布室囊,位于F島的核電站,受9級特大地震影響魁索,放射性物質(zhì)發(fā)生泄漏融撞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一粗蔚、第九天 我趴在偏房一處隱蔽的房頂上張望尝偎。 院中可真熱鬧,春花似錦鹏控、人聲如沸致扯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抖僵。三九已至,卻和暖如春缘揪,著一層夾襖步出監(jiān)牢的瞬間耍群,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工找筝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蹈垢,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓袖裕,卻偏偏與公主長得像曹抬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子急鳄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容