模版模式:優(yōu)雅、靈活地拓展你的pipeline

模版模式,作為一種行為型模式,通過在抽象類或接口中定義一個(gè)操作中的算法骨架,而將一些步驟具體執(zhí)行延遲到子類中實(shí)現(xiàn),從而使得父類的方法執(zhí)行可以獲得不一樣的結(jié)果。從而達(dá)到了代碼復(fù)用、擴(kuò)展性好、靈活度高的設(shè)計(jì)目的。

使用時(shí)機(jī)

模版模式使用時(shí)機(jī),主要是相同、相似方法使用較多的情況。采用模版模式,可以將這些相似的方法提取出來,制定出一個(gè)相對普適的模版,從而減少代碼的重復(fù)書寫,提高代碼的復(fù)用率。抽象化的使用場景及實(shí)現(xiàn)邏輯如下圖所示。

基本定義

在了解如何寫模版模式之前,我們有必要來了解一些有關(guān)模版模式的關(guān)鍵名詞及術(shù)語。

基本方法:

基本方法又可以劃分為如下三類:

1、具體方法(Concrete Method)

具體方法指的是由父類/接口負(fù)責(zé)實(shí)現(xiàn)的方法,子類不可以對該方法進(jìn)行更改。

2、抽象方法(Abstract Method)

抽象方法則指的是不由父類/接口實(shí)現(xiàn)具體步驟,而是將其具體操作步驟推遲到子類實(shí)現(xiàn),從而對不同情況實(shí)現(xiàn)不同的操作。

3、鉤子方法(Hook Method)

    一個(gè)鉤子方法由抽象類聲明并實(shí)現(xiàn),而子類會(huì)加以擴(kuò)展。**它是子類可以選擇性實(shí)現(xiàn)或不實(shí)現(xiàn)的方法**,通常抽象類給出是一個(gè)空實(shí)現(xiàn),作為方法的默認(rèn)實(shí)現(xiàn)。

    這樣的默認(rèn)實(shí)現(xiàn),被稱為**默認(rèn)鉤子方法**。這種空鉤子方法也叫做“Do Nothing Hook”。默認(rèn)鉤子方法在缺省適配模式也有相應(yīng)的使用。缺省適配模式講的是一個(gè)類為接口提供一個(gè)默認(rèn)的空實(shí)現(xiàn),從而使得子類不必給出所有方法的實(shí)現(xiàn),因?yàn)橥ǔR粋€(gè)具體類并不需要所有的方法。這個(gè)思想正好同默認(rèn)鉤子方法不謀而合。

    鉤子方法常見的用途為,將兩個(gè)存在不同調(diào)用關(guān)系的pipeLine流程,通過鉤子方法聯(lián)系到同一個(gè)模版中,從而屏蔽不同內(nèi)容的差異性。但是,需要注意的一點(diǎn)是,**鉤子方法的名字應(yīng)當(dāng)以do開始,這是熟悉設(shè)計(jì)模式的Java開發(fā)人員的標(biāo)準(zhǔn)做法。**如doScan、doGet等。

模版方法:

    模版方法是模版模式的核心點(diǎn),其是定義在抽象類中的,是把基本操作方法組合在一起形成總的算法或行為的方法。一個(gè)抽象類可以有**任意多個(gè)模板方法**,而不限于一個(gè)。每一個(gè)模板方法都可以調(diào)用任意多個(gè)具體方法。原則上,**子類不可以、也不應(yīng)該對模版方法進(jìn)行覆蓋或者重寫**。

上述定義中各類方法的對應(yīng)模塊大致如下圖所示:

代碼實(shí)踐

模版模式的實(shí)現(xiàn),在java中有兩種方式,一種是基于抽象類的實(shí)現(xiàn)方式,另外一種則是基于接口的實(shí)現(xiàn)方式。

這里我們以抽象類的實(shí)現(xiàn)方法為例子介紹相應(yīng)的模版模式的實(shí)現(xiàn)。

public abstract class Template {

    public void concreteMethod() {
        System.out.println("concreteMethod:");
    }

    public abstract void abstractMethod();

    public void hookMethod(){
        System.out.println("hookMethod:");
        System.out.println("實(shí)現(xiàn)默認(rèn)hookMethod!");
    }


    public final void execute() {
        concreteMethod();

        abstractMethod();

        hookMethod();
    }
}

首先,定義出我們的模版接口,其中包含三個(gè)方法concreteMethod、abstractMethod、hookMethod。就分別對應(yīng)于我們上述提到的具體方法、抽象方法及鉤子方法

然后在execute()方法內(nèi),定義好三個(gè)方法的基本執(zhí)行方法,同時(shí)采用final修飾符,使得子類無法修改execute方法中的執(zhí)行順序。

然后在我們的子類HerFuction中,首先必須要對抽象方法進(jìn)行相應(yīng)的實(shí)現(xiàn)。這里我們簡單的輸出類名。

而在鉤子方法hookMethod中,我們則對原方法進(jìn)行增強(qiáng),多輸出一句話:“我還要執(zhí)行自己的hookMethod方法!”。

public class HerFunction implements Template {

    @Override
    public void abstractMethod() {
        System.out.println("HerFunciton !");
    }

    @Override
    public void hookMethod() {
        Template.super.hookMethod();
        System.out.println("我還要執(zhí)行自己的hookMethod方法!");
    }
}

類似地,在第二個(gè)子類MyFunction中,我們也需要實(shí)現(xiàn)相應(yīng)的抽象類方法。但對于鉤子方法則采用默認(rèn)的抽象類中的方法實(shí)現(xiàn)即可。

public class MyFunction extends Template {

    @Override
    public void abstractMethod() {
        System.out.println("My Function!");
    }
}

最后,在啟動(dòng)方法中分別創(chuàng)建MyFunction、HerFunction對應(yīng)的對象,并調(diào)用父類的execute方法即可。

    public static void main(String[] args) {
        Template myFunction = new MyFunction();
        myFunction.execute();
        System.out.println("================我是分割線=========================");
        Template herFunction = new HerFunction();
        herFunction.execute();
    }

最后得到的結(jié)果如下:

可以看到,子類對concreteMethod方法都成功實(shí)現(xiàn)了復(fù)用,而對于abstractMethod則根據(jù)不同子類實(shí)現(xiàn)了不同的邏輯,體現(xiàn)了差異性。同時(shí)鉤子方法的默認(rèn)實(shí)現(xiàn)及子類實(shí)現(xiàn),也體現(xiàn)了模版的靈活性。

優(yōu)缺點(diǎn)分析

優(yōu)點(diǎn):

1、利用模板模式將相同處理邏輯的代碼放到抽象父類中,可以提高代碼的復(fù)用性。

2、將相同業(yè)務(wù)含義的處理代碼放置到不同的子類中,通過對子類的擴(kuò)展增加新的行為,從而提高代碼的擴(kuò)展性。

3、把不變的行為寫在父類上,去除子類的重復(fù)代碼,提供了一個(gè)很好的代碼復(fù)用平臺,符合開閉原則。

缺點(diǎn):

1、模版模式的實(shí)現(xiàn)依賴于子類的構(gòu)建,因此類的數(shù)量會(huì)存在明顯的增加,增加了類的復(fù)雜度。

2、采用抽象類情況下,繼承關(guān)系自身存在一定缺點(diǎn),如果父類添加新的抽象方法,所有子類都要對該抽象方法進(jìn)行實(shí)現(xiàn)。JAVA語言可以采用接口+default關(guān)鍵字的方式,一定程度上避免這個(gè)修改。(但是帶來的副作用是不能采用final對方法進(jìn)行限制)

參考文獻(xiàn)

《JAVA設(shè)計(jì)模式》之模板模式(Template)

模版模式

詳解Java8接口中引入default關(guān)鍵字的本質(zhì)原因

模板模式的優(yōu)缺點(diǎn)

最后編輯于
?著作權(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)容