模板方法模式

一 定義

在面向?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ù)約束其行為。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容