設(shè)計(jì)模式-模版方法模式

設(shè)計(jì)模式-模版方法模式

定義

模版方法模式(Template Method Pattern)又叫模版模式,是指定義一個(gè)操作中的算法的框架,而將一些步驟延遲到子類中.使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟,屬于行為型設(shè)計(jì)模式.

模版方法模式實(shí)際上是封裝了一個(gè)固定流程,該流程由幾個(gè)步驟組成,具體步驟可以由子類進(jìn)行不同實(shí)現(xiàn),從而讓固定的流程產(chǎn)生不同的結(jié)果.它非常簡(jiǎn)單,其實(shí)就是類的繼承機(jī)制,但它卻是一個(gè)應(yīng)用非常廣泛的模式.模版模式的本質(zhì)抽象封裝流程,具體進(jìn)行實(shí)現(xiàn).

模版方法模式的應(yīng)用場(chǎng)景

當(dāng)一個(gè)操作具有固定的流程時(shí),由抽象固定流程步驟,具體步驟交給子類進(jìn)行具體實(shí)現(xiàn)(固定的流程,不同的實(shí)現(xiàn)).

在我們的日常生活當(dāng)中,模版方法非常的常見.比如以下流程:

辦理入職流程可以使用模版模式
再比如炒菜流程

再比如趙本山老師的經(jīng)典小品中的一個(gè)段子,把大象放進(jìn)冰箱需要幾步?

把大象放進(jìn)冰箱需要3步O.o

那么,同學(xué)們,我們接著研究一下:把長頸鹿放進(jìn)冰箱需要幾步?還是3步嗎?

-

-

-

-

-

哈哈,這次需要4步~~至于為什么不一樣了,后續(xù)我們會(huì)講到鉤子方法...

從以上的案例中,我們不難總結(jié)出模版方法模式的適用場(chǎng)景:

1萄涯、一次性實(shí)現(xiàn)一個(gè)算法的不變的部分,并將可變的行為留給子類來實(shí)現(xiàn).

2、各子類中公公的行為被提取出來并集中到一個(gè)公共的父類中,從而避免代碼重復(fù).

首先,我們看一下模版方法的通用UML靜態(tài)類圖:

通用靜態(tài)類圖

在UML類圖中,我們不難看到,模版方法模式主要包含兩種角色:

抽象模版(AbstractClass):抽象模版類,定義了一套算法框架/流程;

具體實(shí)現(xiàn)(ConcreteClass):具體實(shí)現(xiàn)類,對(duì)算法框架/流程中的某些步驟進(jìn)行了實(shí)現(xiàn).

模版方法模式中的鉤子方法

我們繼續(xù)以趙本山老師的冰箱裝大象事件為例,通過代碼來實(shí)現(xiàn):

創(chuàng)建抽象模板類

抽象模板類中有個(gè)鉤子方法,這里解釋一下.設(shè)計(jì)鉤子方法的主要目的用來干預(yù)執(zhí)行流程,使得我們能夠控制執(zhí)行流程,是其更符合實(shí)際業(yè)務(wù)需求.鉤子方法的返回值一般為適合條件分支語句的返回值(如:boolean充边、int等).小伙伴們可以根據(jù)自己的實(shí)際業(yè)務(wù)場(chǎng)景決定是否使用鉤子方法.

裝大象實(shí)現(xiàn)類
裝長頸鹿實(shí)現(xiàn)類
測(cè)試方法
運(yùn)行結(jié)果
冰箱裝大象的UML類圖

通過這個(gè)案例,相信小伙伴們一定對(duì)模版方法及鉤子方法有了一個(gè)初步的認(rèn)識(shí).為了加深理解,我們一起去探查另一個(gè)應(yīng)用案例.

利用模版方法模式重構(gòu)JDBC操作業(yè)務(wù)場(chǎng)景

創(chuàng)建一個(gè)模版累JdbcTemplate,封裝所有的JDBC操作.以查詢?yōu)槔?每次查詢的表不同,返回的數(shù)據(jù)結(jié)構(gòu)也不一樣.我們針對(duì)不同的數(shù)據(jù),都要封裝成不同的實(shí)體對(duì)象.而每個(gè)實(shí)體封裝的邏輯都是不一樣的,但封裝前和封裝后的處理流程是不變的,因此,我們可以使用模版方法模式來設(shè)計(jì)這樣的業(yè)務(wù)場(chǎng)景.先創(chuàng)建約束ORM邏輯的接口RowMapper:

接口RowMappe

再創(chuàng)建封裝了所有處理流程的抽象類JdbcTemplate:

抽象類JdbcTemplate
實(shí)體對(duì)象Member
數(shù)據(jù)庫操作類MemberDao
測(cè)試方法

希望通過以上兩個(gè)案例的業(yè)務(wù)場(chǎng)景分析,能夠幫助小伙伴們對(duì)模版方法模式有比較深入的理解.

模版方法模式在源碼中的應(yīng)用

先來看JDK中的AbstractList,來看代碼:

抽象類AbstractList

我們看到get()是一個(gè)抽象方法,那么它的邏輯就是交給子類來實(shí)現(xiàn),我們大家熟悉的ArrayList就是AbstractList的子類.同理,有AbstractList就有AbstractSet和AbstractMap,感興趣的小伙伴們可以去看看這些的源碼實(shí)現(xiàn).還有一個(gè)每天都在用的HttpServlet,有3個(gè)方法:service()方法恤煞、doGet()方法和doPost()方法,都是模版方法的抽象實(shí)現(xiàn).

在Mybatis框架也有一些經(jīng)典的應(yīng)用,我們來看一下BaseExecutor類,它是一個(gè)基礎(chǔ)的SQL執(zhí)行類,實(shí)現(xiàn)了大部分的SQL執(zhí)行邏輯,然后把幾個(gè)方法教給子類定制化完成,源碼如下:

抽象類BaseExecutor

如:doUpdate()椅寺、doFlushStatements()梯影、doQuery()、doQueryCursor()這幾個(gè)方法就是由子類來實(shí)現(xiàn)的,那么BaseExecutor有哪些子類呢?我們來看一下它的類圖:

BaseExecutor靜態(tài)類圖

我們?cè)賮砜匆幌耂impleExecutor的doUpdate實(shí)現(xiàn):

SimpleExecutor的doUpdate實(shí)現(xiàn)

再來對(duì)比一下BatchExecutor的doUpdate實(shí)現(xiàn):

BatchExecutor的doUpdate實(shí)現(xiàn)

通過對(duì)比,我們不難發(fā)現(xiàn)兩者的差異.封裝抽象流程,具體進(jìn)行實(shí)現(xiàn).感興趣的小伙伴可以繼續(xù)深入研究一波MyBatis源碼,我們這里就不繼續(xù)深挖啦.

模版方法模式的優(yōu)點(diǎn)

1诅挑、利用模版方法將相同處理邏輯的代碼放到抽象父類中,可以提高代碼的復(fù)用性.

2四敞、在不同的子類中,通過對(duì)子類的擴(kuò)展增加新的行為,提高代碼的擴(kuò)展性.

3、把不變的行為寫在父類中,去除子類的重復(fù)代碼,提供了一個(gè)很好的代碼復(fù)用平臺(tái),符合開閉原則.

模版方法模式的缺點(diǎn)

1拔妥、類數(shù)目增加,每個(gè)抽象類都需要至少一個(gè)子類來實(shí)現(xiàn),這樣導(dǎo)致類的數(shù)量增加.

2忿危、類數(shù)量的增加,間接地增加了系統(tǒng)實(shí)現(xiàn)的復(fù)雜度.

3、繼承關(guān)系自身缺點(diǎn),如果父類添加新的抽象方法,所有子類都要改一遍.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末没龙,一起剝皮案震驚了整個(gè)濱河市铺厨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌硬纤,老刑警劉巖解滓,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異筝家,居然都是意外死亡洼裤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門溪王,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腮鞍,“玉大人值骇,你說我怎么就攤上這事÷萍酰” “怎么了雷客?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長桥狡。 經(jīng)常有香客問我搅裙,道長,這世上最難降的妖魔是什么裹芝? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任部逮,我火速辦了婚禮,結(jié)果婚禮上嫂易,老公的妹妹穿的比我還像新娘兄朋。我一直安慰自己,他們只是感情好怜械,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布颅和。 她就那樣靜靜地躺著,像睡著了一般缕允。 火紅的嫁衣襯著肌膚如雪峡扩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天障本,我揣著相機(jī)與錄音教届,去河邊找鬼。 笑死驾霜,一個(gè)胖子當(dāng)著我的面吹牛案训,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播粪糙,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼强霎,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了蓉冈?” 一聲冷哼從身側(cè)響起脆栋,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎洒擦,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怕膛,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡熟嫩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了褐捻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片掸茅。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡椅邓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出昧狮,到底是詐尸還是另有隱情景馁,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布逗鸣,位于F島的核電站合住,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏撒璧。R本人自食惡果不足惜透葛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望卿樱。 院中可真熱鬧僚害,春花似錦、人聲如沸繁调。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹄胰。三九已至岳遥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間烤送,已是汗流浹背寒随。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帮坚,地道東北人妻往。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像试和,于是被迫代替她去往敵國和親讯泣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

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