設(shè)計(jì)模式筆記(九): 模板方法模式

喝飲料

平時我們喝茶或者喝咖啡一般經(jīng)歷以下四個步驟(星巴克等享受生活的土豪請稍微忍耐一下):

  1. 燒開水
  2. 用水沖泡
  3. 泡好之后倒入杯中
  4. 加入調(diào)料

我們可以寫出如下代碼:

public class Coffee {


    public void start() {
        prepare();
        System.out.println("開始喝咖啡");
    }

    private void prepare() {
        boil(); //燒水
        brew(); //沖泡
        poure(); //倒入
        addCondiments(); //加入調(diào)料
    }

    private void boil() {
        System.out.println("燒水");
    }

    private void brew() {
        System.out.println("沖泡咖啡");
    }

    private void poure() {
        System.out.println("倒入杯中");
    }

    private void addCondiments() {
        System.out.println("加一些調(diào)料(糖等)");
    }
}

代碼非常簡單,就是將上述過程描述了一遍。

現(xiàn)在如果我們想泡茶怎么辦?行吧,再寫一個Tea類。如下所示:

public class Tea {

    public void start() {
        prepare();
        System.out.println("可以喝茶了");
    }

    private void prepare() {
        boil(); //燒水
        brew(); //沖泡
        poure(); //倒入
        addCondiments(); //加入調(diào)料
    }

    private void boil() {
        System.out.println("燒水");
    }

    private void brew() {
        System.out.println("沖泡茶葉");
    }

    private void poure() {
        System.out.println("倒入杯中");
    }

    private void addCondiments() {
        System.out.println("加一些調(diào)料");
    }
}

看出一些端倪了吧,prepare()方法完全一樣,而且boil()和poure()方法也完全一樣。本著“不能大量出現(xiàn)重復(fù)代碼”的原則,怎么著也得想辦法抽象一下。

將喝飲料這個過程抽象一下

代碼如下:


//飲料類
public abstract class Beverage {

    protected void prepare() {
        boil(); //燒水
        brew(); //沖泡
        poure(); //倒入
        addCondiments(); //加入調(diào)料
    }

    private void boil() {
        System.out.println("燒水");
    }

    protected abstract void brew();


    private void poure() {
        System.out.println("倒入杯中");
    }

    protected abstract void addCondiments();

}

//改變后的咖啡類
public class Coffee extends Beverage {


    public void start() {
        prepare();
        System.out.println("開始喝咖啡");
    }

    @Override
    protected void brew() {
        System.out.println("沖泡咖啡");
    }

    @Override
    protected void addCondiments() {
        System.out.println("加入調(diào)料糖");
    }


}

//改變后的茶類
public class Tea extends Beverage {

    public void start() {
        prepare();
        System.out.println("可以喝茶了");
    }

    @Override
    protected void brew() {
        System.out.println("沖泡茶葉");
    }

    @Override
    protected void addCondiments() {
        System.out.println("我喝茶不想加什么東西");
    }

}

將相同的部分抽離到了抽象類中,子類繼承抽象類,實(shí)現(xiàn)一些抽象方法即可。但是這里不單單是抽象,注意到prepare()方法,這個方法里調(diào)用了其他方法,而且是有順序的調(diào)用,所以這個方法可以稱為“算法的框架”,也就是說這個方法僅僅是一個骨架,定義了各個步驟的順序,不過這些步驟的具體實(shí)現(xiàn)完全可以不一樣,甚至可以將實(shí)現(xiàn)推遲到子類實(shí)現(xiàn),由子類來決定該如何實(shí)現(xiàn),這就是“模板方法模式”。

模板方法模式特點(diǎn)

  1. 提高代碼復(fù)用。通過繼承將相同的代碼放入抽象基類中。
  2. 便于擴(kuò)展,比較靈活。當(dāng)需要新增子類的時候,只需要繼承抽象基類,然后重寫一些方法即可。
  3. 由于引入了抽象類,所以可能會導(dǎo)致子類非常多。

小結(jié)

現(xiàn)在可以給出模板方法模式的定義了:模板方法模式在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變算法結(jié)構(gòu)的情況下,重新定義算法中的某些步驟

本系列文章參考書籍是《Head First 設(shè)計(jì)模式》,文中代碼示例出自書中。

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

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

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