一 定義
在面向?qū)ο蟮某绦蛟O(shè)計(jì)中,我們經(jīng)常會(huì)遇到這種情況,設(shè)計(jì)一個(gè)系統(tǒng)時(shí),知道了算法所需的關(guān)鍵步驟,而且確定了步驟的執(zhí)行順序,但某些步驟的具體實(shí)現(xiàn)還未知,后者說某些步驟的實(shí)現(xiàn)和具體的環(huán)境相關(guān)。
例如,你去銀行辦理業(yè)務(wù),流程大致為,取號,排隊(duì),辦理具體業(yè)務(wù)等,這些步驟的執(zhí)行順序已經(jīng)確定了,可以放在父類中實(shí)現(xiàn),但是辦理具體的業(yè)務(wù)因人而異,有可能是存款,取款,轉(zhuǎn)賬等,這個(gè)是可以延遲到子類中的。
定義:定義一個(gè)操作中的算法的框架,而將一些步驟延遲到子類中,使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
模板方法模式可以用四個(gè)字概括:流程封裝
二 模式結(jié)構(gòu)

角色介紹:
- AbsTemplate:抽象類,定義了一套算法框架。
- ConcreteImplA、ConcreteImplB:具體的實(shí)現(xiàn)。
三 實(shí)例
我們以沖泡咖啡和泡茶為例,沖泡的基本流程是:
1、把水煮沸
2、用煮沸的水沖泡咖啡或者茶葉
3、把沖泡好以后的咖啡或者茶葉倒入杯子
4、加蜂蜜(茶葉)或者加糖和牛奶(咖啡)
算法的框架已經(jīng)有了,具體的實(shí)現(xiàn)可能要延遲到子類中。具體代碼實(shí)現(xiàn)如下:
- 算法抽象類
該抽象類中已經(jīng)定義了算法的實(shí)現(xiàn)步驟,但是第二步和第四步定義成抽象的,需要在子類中實(shí)現(xiàn)。
public abstract class Beverage {
/**
* 煮開水
*/
public void boilWater(){
System.out.println("煮開水");
}
/**
* 沖泡
*/
public abstract void brew();
/**
* 倒進(jìn)杯子
*/
public void pourInCup(){
System.out.println("倒進(jìn)杯子");
}
/**
* 加點(diǎn)東西
*/
public abstract void addSomething();
/**
* 沖泡茶葉或者咖啡流程
* 用final修飾,防止算法被改寫
*/
public final void create(){
boilWater();
brew();
pourInCup();
addSomething();
}
}
- 具體的實(shí)現(xiàn)
實(shí)現(xiàn)沖泡咖啡和茶,實(shí)現(xiàn)抽象類中定義的抽象方法。
public class Coffee extends Beverage{
@Override
public void brew() {
System.out.println("用水沖咖啡");
}
@Override
public void addSomething() {
System.out.println("往咖啡里加點(diǎn)糖或者牛奶");
}
}
public class Tea extends Beverage{
@Override
public void brew() {
System.out.println("用水沖茶");
}
@Override
public void addSomething() {
System.out.println("加點(diǎn)蜂蜜");
}
}
- 測試代碼
// 制作咖啡
System.out.println("------制作coffee----------");
Coffee coffee=new Coffee();
coffee.create();
// 制作茶
System.out.println("------制作tea----------");
Tea tea=new Tea();
tea.create();
-
運(yùn)行結(jié)果
四 優(yōu)缺點(diǎn)
- 封裝不變部分,擴(kuò)展可變部分
把認(rèn)為是不變的部分的算法封裝到父類中,而可變部分則可以通過繼承來繼續(xù)擴(kuò)展。 - 提取公共部分代碼,便于維護(hù)
- 行為由父類控制,子類實(shí)現(xiàn)
缺點(diǎn):模板方法會(huì)帶來代碼閱讀的難度,會(huì)讓用戶覺得難以理解。
五 使用場景
- 多個(gè)子類有公有的方法,并且邏輯基本相同。
- 重要,復(fù)雜的算法,可以把核心算法設(shè)計(jì)成模板方法,周邊的相關(guān)細(xì)節(jié)功能則由各個(gè)子類實(shí)現(xiàn)。
- 重構(gòu)時(shí),模板方法模式是一個(gè)經(jīng)常使用的模式,把相同的代碼抽取到父類中,然后通過鉤子函數(shù)約束其行為。
