引言
無論是現(xiàn)實(shí)生活還是實(shí)際開發(fā)中旁趟,我們常常會遇到一類相似的行為浦楣,他們都包含相似的基本操作和固定的流程汁汗,不同的是他們在不同的業(yè)務(wù)場景下,這些基本操作的具體實(shí)現(xiàn)有所不同妇斤,但是執(zhí)行流程模式都是相同摇锋,當(dāng)然最簡單的話我們針對不同的業(yè)務(wù)區(qū)實(shí)現(xiàn)對應(yīng)的基本操作丹拯,但那是很low的,代碼質(zhì)量堪憂荸恕,明明是重復(fù)的代碼就沒有必要存在了乖酬,模板方法模式就是解決這樣的問題,同時還可以讓后面接手的開發(fā)同學(xué)用最少的代碼融求、最簡單的方式來復(fù)用并實(shí)現(xiàn)更多的業(yè)務(wù)咬像。
一、模板方法概述
模板方法模式是一種類的行為型模式生宛,在它的結(jié)構(gòu)圖中只有類之間的繼承關(guān)系县昂,沒有對象關(guān)聯(lián)關(guān)系,模板方法模式(Template Method Pattern)官方定義:定義一個操作中的算法的框架陷舅,而將一些步驟延遲到子類中倒彰,使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。(Define the skeleton of an algorithm in an operation,deferring some steps to subclasses.Template
Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's
structure.)是不是很裝X莱睁,通俗來說模板方法模式本質(zhì)僅僅是使用了Java的繼承機(jī)制待讳,封裝幾個抽象方法和一個具體模板方法。模板方法模式中作為父類的抽象類叫做抽象模板AbstractClass仰剿,抽象模板中的基本方法盡量設(shè)計為protected類型创淡,符合迪米特法則,不需要暴露的屬性或方法盡量不要設(shè)置為protected類型南吮。實(shí)現(xiàn)類若非必要辩昆,盡量不要擴(kuò)大父類中的訪問權(quán)限;繼承抽象模板的就叫做具體模板旨袒,抽象模板中包含三種類型的方法: 基本方法汁针、模板方法和鉤子方法(Hook Method)。
基本方法——基本方法也叫做基本操作砚尽,是由子類實(shí)現(xiàn)的方法施无,并且在模板方法被調(diào)用。
模板方法——核心方法必孤,不允許子類重寫猾骡,所以都會加上final修飾符,可以有一個或幾個敷搪,一般是一個具體方法框架兴想,按照固定的流程對基本方法的調(diào)度
鉤子方法——為了讓模板方法的執(zhí)行結(jié)果的更好地適應(yīng)因外界條件改變。比如說銀行辦理業(yè)務(wù)為例赡勘,辦理業(yè)務(wù)是個模板方法嫂便,普通人要經(jīng)歷排隊、取號闸与、等待毙替、辦理四個基本流程岸售,而Vip則不需要排隊、取號厂画、等待凸丸,那么在設(shè)計的時候我們的抽象模板類需要考慮到,于是乎你得需要在模板方法各基本方法調(diào)用之前增加條件判斷袱院,那么用于設(shè)置這個條件的方法就是屎慢,鉤子方法(Hook Method),鉤子方法也可以是抽象的還可以由子類的一個方法返回值決定公共部分的執(zhí)行結(jié)果忽洛。
二腻惠、模板方法的優(yōu)點(diǎn)和缺點(diǎn)及常見可用場景
1、模板方法模式的優(yōu)點(diǎn)
良好的擴(kuò)展性脐瑰,封裝不變部分妖枚,擴(kuò)展可變部分,把認(rèn)為是不變部分的算法封裝到父類實(shí)現(xiàn)苍在,而可變部分的則可以通過繼承來繼續(xù)擴(kuò)展绝页。例如增加一個新的功能很簡單,只要再增加一個子類寂恬,實(shí)現(xiàn)父類的基本方法就可以了续誉。
提取公共部分代碼,便于維護(hù)初肉,減小維護(hù)升級成本酷鸦,基本操作由父類定義,子類實(shí)現(xiàn)
基本方法是由子類實(shí)現(xiàn)的牙咏,因此子類可以通過擴(kuò)展的方式增加相應(yīng)的功能臼隔,符合開閉原 則。
2妄壶、模板方法模式的缺點(diǎn)
通常抽象類是負(fù)責(zé)聲明某一類的事物的共同屬性和抽象方法摔握,實(shí)現(xiàn)類則是完成定義具體的特性和方法。但是模板方法模式卻顛倒了丁寄,抽象類定義了部分抽象方法氨淌,由子類實(shí)現(xiàn),子類執(zhí)行的結(jié)果影響了父類的結(jié)果伊磺,也就是子類對父類產(chǎn)生了影響盛正,可能會讓新手產(chǎn)生不適感,以下不理解代碼屑埋。
3豪筝、適合使用模板方法模式的場景
多個子類有公有的方法,并且邏輯基本相同時。
重要壤蚜、復(fù)雜的算法即寡,可以把核心算法設(shè)計為模板方法碘饼,周邊的相關(guān)細(xì)節(jié)功能則由各個 子類實(shí)現(xiàn)顶吮。
重構(gòu)時横堡,模板方法模式是一個經(jīng)常使用的模式,把相同的代碼抽取到父類中著蟹,然后通過鉤子方法約束其行為。
三梢莽、模板方法的實(shí)現(xiàn)
如下圖所示模板方法模式很簡單萧豆,通俗來說模板方法本質(zhì)上封裝了一個固定的工作流程,相似的一類事務(wù)都按照固定的流程來執(zhí)行昏名,整個結(jié)構(gòu)就全部在一個抽象模板類里
前面所說模板方法模式是基于繼承的代碼復(fù)用基本技術(shù)涮雷,在模板方法模式中,可以將相同的代碼放在父類中轻局,而將不同的方法實(shí)現(xiàn)放在不同的子類中洪鸭。所以實(shí)現(xiàn)起來步驟很簡單:
1、定義抽象模板類
將部分邏輯以具體方法以及具體構(gòu)造函數(shù)的形式實(shí)現(xiàn)仑扑,然后聲明一些抽象方法來讓子類實(shí)現(xiàn)剩余的邏輯览爵,并且定義鉤子方法控制基本方法的執(zhí)行。
public abstract class AbstractClass {
//基本方法1
protected abstract void doOneStep();
//基本方法2
protected abstract void doSecStep();
//基本方法3
protected abstract void doThirdStep();
//模板方法,為了避免被子類覆寫改變模板方法的算法骨架一般使用final修飾镇饮,可以有N個模板方法
public final void work(){
/*
* 調(diào)用基本方法蜓竹,完成相關(guān)的邏輯
*/
if(oneStepNeedRun){//鉤子方法控制基本方法是否執(zhí)行
this.doOneStep();
}
this.doSecStep();
this.doThirdStep();
}
//鉤子方法它在抽象類中不做事或者是默認(rèn)的事情,子類可以選擇覆蓋它储藐,可以有N個
protected boolean oneStepNeedRun(){
return true;
}
}
2俱济、繼承抽象模板類實(shí)現(xiàn)具體模板類
就是普通的繼承,根據(jù)各自的業(yè)務(wù)需要可以選擇是否覆寫鉤子方法的實(shí)現(xiàn)邏輯钙勃。
public class ConcreteClass extends AbstractClass {
//實(shí)現(xiàn)基本方法
protected void doOneStep() {
//業(yè)務(wù)邏輯處理
}
protected void doSecStep() {
//業(yè)務(wù)邏輯處理
}
protected void doThirdStep() {
//業(yè)務(wù)邏輯處理
}
}
測試
public class TemplateMethod {
public static void main(String[] args) {
AbstractClass obj = new ConcreteClass();//多態(tài)構(gòu)建
//調(diào)用模板方法
obj.work();
}
}
小結(jié)
模板方法模式是一種類的行為型模式蛛碌,在它的結(jié)構(gòu)圖中只有類之間的繼承關(guān)系,沒有對象關(guān)聯(lián)關(guān)系肺缕。
模板方法模式是基于繼承和多態(tài)的代碼復(fù)用基本技術(shù)
在模板方法模式中左医,將固定的相同的功能的代碼段放在父類并在父類中實(shí)現(xiàn),而將需要根據(jù)業(yè)務(wù)而各自實(shí)現(xiàn)的方法統(tǒng)一抽象到父類而把實(shí)現(xiàn)延遲到不同的子類中同木。
在模板方法模式中浮梢,結(jié)構(gòu)很簡單一個抽象類和若干個具體實(shí)現(xiàn)子類,抽象類即抽象模板只是定義了基本的操作方法(抽象模板中的基本方法盡量設(shè)計為protected類型彤路,符合迪米特法則秕硝,不需要暴露
的屬性或方法盡量不要設(shè)置為protected類型。實(shí)現(xiàn)類若非必要洲尊,盡量不要擴(kuò)大父類中的訪問
權(quán)限远豺。)而把實(shí)現(xiàn)延遲到子類中實(shí)現(xiàn)奈偏、以及實(shí)現(xiàn)了用于規(guī)范基本方法調(diào)用流程的模板方法(一般將模板方法聲明為final),最后還可以根據(jù)具體的業(yè)務(wù)區(qū)定義鉤子方法用于控制基本方法的執(zhí)行躯护。最后策略模式和模板方法模式都是用于封裝算法惊来,前者是利用組合和委托模型,而后者則是繼承棺滞。