一文帶你厲害Java設(shè)計(jì)模式中的模板方法
概念
在一個(gè)方法中定義了一個(gè)算法的骨架或者步驟,而將一些步驟延遲到子類中去實(shí)現(xiàn)。模板方法使得子類可以在不改變算法結(jié)構(gòu)的情況下,重新定義算法中的某一些步驟。
該設(shè)計(jì)模式主要針對(duì)這樣一種場(chǎng)景:當(dāng)要做一件事兒的時(shí)候,這件事兒的步驟是固定好的,但是每一個(gè)步驟的具體實(shí)現(xiàn)方式是不一定的。這樣,我們可以把所有要做的事兒抽象到一個(gè)抽象類中,并在該類中定義一個(gè)模板方法。
舉例
去銀行的營(yíng)業(yè)廳辦理業(yè)務(wù)需要以下步驟:1.取號(hào)、2.辦業(yè)務(wù)、3.評(píng)價(jià)。三個(gè)步驟中取號(hào)和評(píng)價(jià)都是固定的流程,每個(gè)人要做的事兒都是一樣的。但是辦業(yè)務(wù)這個(gè)步驟根據(jù)每個(gè)人要辦的事情不同所以需要有不同的實(shí)現(xiàn)。我們可以將整個(gè)辦業(yè)務(wù)這件事兒封裝成一個(gè)抽象類:
/** * 模板方法設(shè)計(jì)模式的抽象類 * @author hollis */ public abstract class AbstractBusinessHandeler { /** * 模板方法 */ public final void execute(){ getRowNumber(); handle(); judge(); } /** * 取號(hào) * @return */ private void getRowNumber(){ System.out.println("rowNumber-00" + RandomUtils.nextInt()); } /** * 辦理業(yè)務(wù) */ public abstract void handle(); //抽象的辦理業(yè)務(wù)方法,由子類實(shí)現(xiàn) /** * 評(píng)價(jià) */ private void judge(){ System.out.println("give a praised"); } }
該類中定義了四個(gè)方法,其中getRowNumber
、judge
這兩個(gè)方法是私有的非抽象方法。他們實(shí)現(xiàn)了取號(hào)和評(píng)價(jià)的業(yè)務(wù)邏輯,因?yàn)檫@兩部分內(nèi)容是通用的。還有一個(gè)抽象的handle
方法,這個(gè)方法需要子類去重寫,根據(jù)辦理業(yè)務(wù)的具體內(nèi)容重寫該方法。還有一個(gè)模板方法就是final類型的execute
方法,他定義好了需要做的事兒和做這些事兒的順序。
現(xiàn)在,有了這個(gè)抽象類和方法,如果有人想要辦理業(yè)務(wù),那么只需要繼承該AbstractBusinessHandeler
并且重寫handle
方法,然后再使用該實(shí)現(xiàn)類的對(duì)象調(diào)用execute
方法,即可完成整個(gè)辦理業(yè)務(wù)的流程。
public class SaveMoneyHandler extends AbstractBusinessHandeler { @Override public void handle() { System.out.println("save 1000"); } public static void main(String []args){ SaveMoneyHandler saveMoneyHandler = new SaveMoneyHandler(); saveMoneyHandler.execute(); } }//output:編號(hào):rowNumber-001 save 1000 give a praised
模板方法模式是結(jié)構(gòu)最簡(jiǎn)單的行為型設(shè)計(jì)模式,在其結(jié)構(gòu)中只存在父類與子類之間的繼承關(guān)系。通過使用模板方法模式,可以將一些復(fù)雜流程的實(shí)現(xiàn)步驟封裝在一系列基本方法中,在抽象父類中提供一個(gè)稱之為模板方法的方法來定義這些基本方法的執(zhí)行次序,而通過其子類來覆蓋某些步驟,從而使得相同的算法框架可以有不同的執(zhí)行結(jié)果。模板方法模式提供了一個(gè)模板方法來定義算法框架,而某些具體步驟的實(shí)現(xiàn)可以在其子類中完成。
鉤子方法
當(dāng)在模板方法中某一些步驟是可選的時(shí)候,也就是該步驟不一定要執(zhí)行,可以由子類來決定是否要執(zhí)行,則此時(shí)就需要用上鉤子。鉤子是一種被聲明在抽象類中的方法,但一般來說它只是空的或者具有默認(rèn)值,子類可以實(shí)現(xiàn)覆蓋該鉤子,來設(shè)置算法步驟的某一步驟是否要執(zhí)行。鉤子可以讓子類實(shí)現(xiàn)算法中可選的部分,讓子類能夠有機(jī)會(huì)對(duì)模板方法中某些一即將發(fā)生的步驟做出反應(yīng)。
還是辦理業(yè)務(wù)的例子,如果來的客戶是vip客戶,那么他就可以不必取號(hào),可以直接辦理業(yè)務(wù)。 修改抽象類如下:
public abstract class AbstractBusinessHandeler { public final void execute(){ if(!isVip()){//如果顧客是vip,則不用排隊(duì) getRowNumber(); } handle(); judge(); } public abstract boolean isVip();//抽象的鉤子方法,由子類實(shí)現(xiàn) private void getRowNumber(){ System.out.println("rowNumber-00" + RandomUtils.nextInt()); } public abstract void handle(); private void judge(){ System.out.println("give a praised"); } }
那么,他的實(shí)現(xiàn)類就可以根據(jù)具體情況來復(fù)寫其中的方法,然后同樣調(diào)用execute
方法。
總結(jié)
1.模板方法模式是一種類的行為型模式,在它的結(jié)構(gòu)圖中只有類之間的繼承關(guān)系,沒有對(duì)象關(guān)聯(lián)關(guān)系。
2.模板方法模式是基于繼承的代碼復(fù)用基本技術(shù),模板方法模式的結(jié)構(gòu)和用法也是面向?qū)ο笤O(shè)計(jì)的核心之一。在模板方法模式中,可以將相同的代碼放在父類中,而將不同的方法實(shí)現(xiàn)放在不同的子類中。
3.在模板方法模式中,我們需要準(zhǔn)備一個(gè)抽象類,將部分邏輯以具體方法以及具體構(gòu)造函數(shù)的形式實(shí)現(xiàn),然后聲明一些抽象方法來讓子類實(shí)現(xiàn)剩余的邏輯。不同的子類可以以不同的方式實(shí)現(xiàn)這些抽象方法,從而對(duì)剩余的邏輯有不同的實(shí)現(xiàn),這就是模板方法模式的用意。模板方法模式體現(xiàn)了面向?qū)ο蟮闹T多重要思想,是一種使用頻率較高的模式。
4.鉤子是一種方法,它在抽象類中不做事,或者是默認(rèn)的事情,子類可以選擇覆蓋它
5.為了防止子類改變模板方法中的算法骨架,一般將模板方法聲明為final
6.策略模式和模板方法都是用于封裝算法,前者是利用組合和委托模型,而后者則是繼承
到此這篇關(guān)于一文帶你厲害Java設(shè)計(jì)模式中的模板方法的文章就介紹到這了,更多相關(guān)Java模板方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA操作HDFS案例的簡(jiǎn)單實(shí)現(xiàn)
本篇文章主要介紹了JAVA操作HDFS案例的簡(jiǎn)單實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08Spring Boot學(xué)習(xí)入門之統(tǒng)一異常處理詳解
我們?cè)谧鯳eb應(yīng)用的時(shí)候,請(qǐng)求處理過程中發(fā)生錯(cuò)誤是非常常見的情況。下面這篇文章主要給大家介紹了關(guān)于Spring Boot學(xué)習(xí)入門之統(tǒng)一異常處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-09-09Hibernate連接三種數(shù)據(jù)庫(kù)的配置文件
今天小編就為大家分享一篇關(guān)于Hibernate連接三種數(shù)據(jù)庫(kù)的配置文件,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03解決mybatis竟然報(bào)Invalid value for getInt()的問題
使用mybatis遇到一個(gè)非常奇葩的問題,總是報(bào)Invalid value for getInt()的問題,怎么解決呢?下面小編通過場(chǎng)景分析給大家代來了mybatis報(bào)Invalid value for getInt()的解決方法,感興趣的朋友參考下吧2021-10-10關(guān)于IDEA使用jsp可以訪問頁(yè)面轉(zhuǎn)換為html彈出頁(yè)面為404的問題
這篇文章主要介紹了關(guān)于IDEA使用jsp可以訪問頁(yè)面轉(zhuǎn)換為html彈出頁(yè)面為404的問題及解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12