標簽: 設(shè)計模式初涉
我有故事,你有酒嗎?這年頭寫個技術(shù)文不講個故事都不行,行,我講;
還有發(fā)現(xiàn)很多的技術(shù)博文都開始有喜歡往文中插入幾個表情的趨勢了,
但是你真的插的姿勢對了嗎?這種事情不是隨便插的,來來來,給你
見識下如何在適當?shù)膱鼍安迦脒m當?shù)谋砬橐宰屪x者感覺到易可賽艇,
本文以講故事插表情為主,講述橋接模式為輔,多圖預(yù)警,
簡書上排版可能有些問題,最佳排版可見:
https://www.zybuluo.com/coder-pig/note/643756
我就喜歡這樣光明正大的開著我的托馬斯小火車,污污污
場景引入
??????在之前的章節(jié)中,我們都知道小豬開家奶茶店,憑借著獨特
的奶茶制作工藝,每天都吸引了一堆吃貨在門口排隊。每天基本
都是坐著收錢,但是喜歡折騰的小豬并不只滿足于賣奶茶和小吃,
他一直在尋求著新的盈利點。一天沒事,他打開了“丑團外賣”,
看著別人做餐飲的怎么玩,咦,有加奶茶店竟然做起了賣煲仔
飯的副業(yè),打著“新品煲仔飯新鮮出爐,買飯送飲料”的廣告口號,
再看下銷量,還不賴,飯 + 飲料 + 小吃,能再從飯里面撈一筆,
但是做什么飯好呢?思前想后還是做技術(shù)水平最低的扒類,去市場
買好扒,買些醬料腌制下,然后丟鐵板上一煎,然后配點飯或者
意粉,成本也就10來塊,妥妥地賣30塊一份,23333
嘿嘿,打算賣這幾樣?xùn)|西:
- 牛扒
- 豬扒
- 牛扒飯
- 豬扒飯
- 牛扒意粉
- 豬扒意粉
接著按照套路來,我們擼下代碼,不用Bridge模式的一般玩法:
先建立一個扒的父類:Steak.java
接著繼承這個扒類編寫牛扒與豬扒子類
再接著繼承豬扒和牛扒,寫出四個子類
準備就開賣了,寫一個餐館類來賣扒:
輸出結(jié)果:
可以,老鐵,沒毛病,就這樣開始搞事情了~
問題初現(xiàn)
新品推出,肯定是搞吃扒送飲料的套路,由此吸引了一大波貪小便宜
的吃貨,人多了,要求也多了,吃貨反饋最多的問題是:
沒有雞扒,這不清真!
視顧客為上帝的小豬,肯定是急急腳把雞扒加上:
然后調(diào)用下就好,又一次解決了吃貨的需要,小豬感到很愉悅。
雞扒是有了,然后吃貨們又說想吃魚扒,照葫蘆畫瓢又得
繼承,寫三個類,有些繁瑣,小豬開始意識到可能有些問題,
但是因為懶和拖拉,還是默默接受了沒毛病這個設(shè)定,然后
沿用原先的套路把魚扒也加上了。
問題又現(xiàn)
?????此時的小豬正悠閑的玩著王者農(nóng)藥,他似乎沒有意思到逐漸
向他靠近的挑戰(zhàn)。店員小B走了過來:
對小豬說: "老板,客人想要羊扒。"
小豬此時正在打團,因為被打斷導(dǎo)致了團滅,有些不悅的說道:
"那就加上啊,按照之前的雞扒魚扒套路玩啊,你怎么那么蠢?"
小B一臉尷尬的說道:客人覺得味道太單一,有的想要加番茄汁,
有的想要加黑椒汁...,我不知道該怎么辦"
小豬突然意識到事態(tài)的嚴重性了,這得繼承N次,建多少個類??!
需要一個人靜靜,然后把手機遞給了小B,語氣凝重的說到:
"這把黃金上鉑金的晉級賽,輸了扣你半個月工資!"
然后揚長而去,小B看了看戰(zhàn)績:0:20:5?站在原地一臉懵逼~
?????小豬一邊走一邊想,按照原有的套路,加上汁又得
加上N多的類,如果顧客又想加配菜呢,這是要GG啊,
這耦合度太高了,舊套路必須推翻,得想個新的套路!
?????走著走著來到一個沒人的地方了,小豬左顧右盼確定
沒人后,悄悄地把自己的手塞到褲襠中,反復(fù)翻動,似乎
在尋找著什么,然后掏出了不可描述的長18.4cm的...
欲望知后事如何請聽下回分解~
讀者老爺:下回個毛線,快把你這破車飚完!
好的,上回說到,小豬從褲襠里掏出了18.4cm長不可描述的東西,
這個到底是什么呢?為何小豬要找沒人的角落才敢掏出來?
此物看上去黑硬粗,離近一看才知道是:
《如何讓孩子愛上設(shè)計模式》
黑色的封面,硬質(zhì)書皮,粗體書名,長18.4cm * 寬13cm
不可描述是因為此書是編程界三十六道絕世功法中的
一本,一但被別人知道了,必然會引起殺身之禍,小豬
小豬雖然已經(jīng)掌握了其中的二十三式中的前九式,但是
還是沒有自保的能力,所以平日只能藏于褲襠之中,
在沒人的地方才敢拿出來反復(fù)研讀。
話說回來,小豬翻開《如何讓孩子愛上設(shè)計模式》快速翻閱
著能夠解決當前問題的設(shè)計模式,當翻到橋接模式的時候,
一段文字映入小豬的眼簾:
在軟件系統(tǒng)中,某些類型由于自身的邏輯,它具有兩個或
多個維度的變化,那么如何應(yīng)對這種“多維度的變化”?
如何利用面向?qū)ο蟮募夹g(shù)來使得該類型能夠輕松的沿著
多個方向進行變化,而又不引入額外的復(fù)雜度?這就要使用Bridge模式。
多維?維度變化?小豬不解,繼續(xù)往下看,看到一句心法:
將抽象部分與實現(xiàn)部分分離,使得他們可以獨立地進行變化!
把變化的因素都分離出來(抽象類),讓他獨立變化(繼承),然后在程序運行時
動態(tài)地將抽象與實現(xiàn)部分組合起來。而多維橋接需要互相持有,
比如這里的扒類持有飯意粉,醬汁類持有扒類!如果再
加上配菜,就加多一個配菜類持有醬汁類!
沒錯,就是這樣,小豬此刻猶如醍醐灌頂,靈魂附體,立馬
飛身趕回店中,已經(jīng)迫不及待的想用橋接模式來秀一波了。
橋接模式初顯威風(fēng)
回到店里的小豬就是一頓瘋狂輸出,把變化因素都抽取出來:
先抽配餐類,畢竟這個是可變的,可飯,可意粉,你喜歡還可以加河粉:
繼承配餐類的飯和意粉
再抽扒類,也是可變的,可牛,可豬,可雞,可魚,可茍
牛扒與豬扒
改良后的賣扒套路:
輸出結(jié)果:
原先要的效果實現(xiàn)了,再加上雞扒和羊扒又如何:
就是這么簡單,什么魚扒,狗扒隨便來,唰唰唰就加上了,
小豬表示無所畏懼!
橋接模式再顯神威
??????正當小豬沾沾自喜的時候,店員小B急沖沖地跑進來喊道:
“小豬老板,前幾天要加醬汁的顧客又來鬧事啦!??!啊!啊!”
小豬很淡定的說到:“莫方莫方,帶我出去看看,我自能解決!”
剛出店門,小豬就被眼前的景象所驚呆了:
恢復(fù)了一下情緒后,小豬問到:“就是你們?nèi)齻€加醬汁是吧?”
跳舞的基佬:“是的,我們分別要黑椒汁,番茄汁和香草汁,今天
要是不給我們搞,我們就繼續(xù)在這里跳舞,只要有空地,哪里都能跳尬舞!”
小豬微微一笑,說到:“呵呵,原來是砸場子的,今日倒要給你們看看我的本事!”
跳舞的基佬一驚:
,然后開始瘋狂操作了起來!
變化的是醬汁,把他抽取出來,持有扒類
番茄汁,黑椒汁,還有香草汁
接著是調(diào)用部分
輸出結(jié)果:
跳舞基佬開始慫了,邊說邊退后道:"你...豬哥村夫,你敢..."
小豬哥義正言辭到:"住口,三只斷脊之犬,也敢在我店門前狺狺狂吠"!
三個跳舞基佬發(fā)出“啊”的叫聲后,應(yīng)聲倒地不起。
小豬補刀到:
圍觀群眾無不拍手叫好,厲害厲害!
戲看完了,圍觀群眾也散了,大獲全勝的小豬大搖大擺地走回店里,
而此時他卻沒發(fā)現(xiàn),在暗處里站著一個人:
“原來《如何讓孩子愛上設(shè)計模式》的功法在你手上,呵呵”,
隨之露出一抹冷笑,接著消失在空氣中...
小豬突然覺得背后一涼,回頭一看卻發(fā)現(xiàn)空無一人:
小豬安慰著說:“可能是心理作用吧!”,然后又繼續(xù)玩農(nóng)藥了。
躲在暗處的人到底是誰呢?為什么她會知道小豬持有長18.4cm黑硬粗的
——《如何讓孩子愛上設(shè)計模式》功法呢?是敵是友?是女是女?
小豬又會遇上怎樣的危機呢?又會發(fā)生怎樣的故事呢?
欲知后事如何,請聽下回分解...
======= 本章完 =======
好的,故事聽完了,接下來講一波概念性的東西~
橋接模式的定義
橋接模式基于單一職責(zé)原則,如果系統(tǒng)中的類存在多個
變化的維度,通過該模式可以將這幾個維度分離出來,
然后進行獨立擴展。這些分離開來的維度,通過在抽象層
持有其他維度的引用來進行關(guān)聯(lián),就好像在兩個維度間
搭了橋一樣,所以叫橋接模式。
四個角色
Abstraction:抽象部分的接口。通常在這個對象里面,要維護一個實現(xiàn)部分
的對象引用,在抽象對象里面的方法,需要調(diào)用實現(xiàn)部分的對象來完成。
這個對象里面的方法,通常都是跟具體的業(yè)務(wù)相關(guān)的方法。Refined Abstraction:擴展抽象部分的接口,通常在這些對象里面,
定義跟實際業(yè)務(wù)相關(guān)的方法,這些方法的實現(xiàn)通常會使用Abstraction中
定義的方法,也可能需要調(diào)用實現(xiàn)部分的對象來完成。Implementor:定義實現(xiàn)部分的接口,這個接口不用和Abstraction
里面的方法一致,通常是由Implementor接口提供基本的操作,而
Abstraction里面定義的是基于這些基本操作的業(yè)務(wù)方法,也就是說
Abstraction定義了基于這些基本操作的較高層次的操作。ConcreteImplementor:真正實現(xiàn)Implementor接口的對象。
UML類圖
優(yōu)缺點
優(yōu)點:
- 實現(xiàn)了抽象和實現(xiàn)部分的分離,更好的可擴展性,動態(tài)切換實現(xiàn),
- 很多情況下橋接模式可以替代多層繼承方案,極大減少子類個數(shù)!
缺點:
- 增加系統(tǒng)的理解與設(shè)計難度,由于關(guān)聯(lián)關(guān)系建立在抽象層,
要求開發(fā)者一開始就針對抽象層進行設(shè)計與編程。 - 要求正確識別出系統(tǒng)中兩個獨立變化的維度,因此其使用
范圍具有一定的局限性,如何正確識別兩個獨立維度也需要
一定的經(jīng)驗積累。
適用場景
多維變化類或者多個樹狀圖間的耦合;
想為構(gòu)建的抽象與具體化提供更多靈活性,避免兩層次間建立靜態(tài)的繼承聯(lián)系;
不希望使用繼承或因多層繼承導(dǎo)致系統(tǒng)類個急劇增加的額系統(tǒng);
一個類存在兩個或多個獨立變化的維度,而且都需要獨立進行擴展。
本文代碼:
https://github.com/coder-pig/DesignPatternsExample/tree/master/9.Bridge%20Pattern