完全透析設計模式(2)- 模板方法

模板方法模式(Template Method)

我曾在一本書上看過作者將模板比喻成帶有鏤空文字的薄薄的塑料版。只要用筆在模板的鏤空處就可以臨摹出整齊的圖案。我們可以通過塑料版上鏤空的洞就可以知道是什麼文字圖案,但是文字圖案具體是什麼顏色的,效果如何,就只能依賴於使用什麼樣的筆去臨摹了。但是文字圖案的形狀一定是和鏤空的圖案一致的。
Alt
模板方法是一種行爲設計模式。通過定義一個抽象類作爲父類,然後聲明一些抽象方法和一個具體的模板方法,模板方法定義了操作調用的框架,即具體調用哪些方法以及調用順序。而方法的具體實現則交給子類,不同的子類就會有不同的實現效果,這也是模板方法設計模式的目的所在。

模板方法的角色

Alt
- 抽象模板(AbstractClass)

抽象模板類AbstractClass負責定義模板方法需要的抽象方法和實現具體的模板方法,模板方法定義了對抽象方法的邏輯調用順序。

- 具體模板(ConcreateClass)

具體模板類繼承抽象模板,負責實現抽象類中定義的抽象方法。

實踐模板方法

假設我們需要在一個運動場舉行各種各樣的體育賽事,每場比賽賽事都包含了運動員進場握手、比賽中、運動員退場、清理場地這樣的步驟。這些步驟會因爲具體賽事的不同會有不同的表現,我們就可以將賽事舉辦過程抽象成爲一個抽象類(即抽象模板)。

/**
 * @Descrtption Game 一場比賽
 * @Author luke
 * @Date 2019/11/20
 **/
public abstract class Game {

    /**模板方法,需要加上final關鍵字*/
    public final void play(){
        handshake();
        fight();
        exit();
        clean();
    }

    /**運動員握手*/
    protected abstract void handshake();

    /**雙方交戰中*/
    protected abstract void fight();

    /**雙方運動員退場*/
    protected abstract void exit();

    /**打掃場地*/
    private final void clean(){
        System.out.println("觀衆退場,打掃場地");
    }

}

定義了抽象模板Game之後,我們就可以定義具體的賽事了,那就來一場拳擊比賽和一場足球比賽吧。這些具體的比賽賽事需要繼承抽象的賽事模板。

/**
 * @Descrtption BoxingGame 拳擊比賽
 * @Author luke
 * @Date 2019/11/20
 **/
public class BoxingGame extends Game{

    @Override
    protected void handshake() {
        System.out.println("用拳套觸碰");
    }

    @Override
    protected void fight() {
        System.out.println("你一拳呀我一拳");
    }

    @Override
    protected void exit() {
        System.out.println("運動員送往醫療室理療");
    }

}
/**
 * @Descrtption FootballGame 足球比賽
 * @Author luke
 * @Date 2019/11/20
 **/
public class FootballGame extends Game{

    @Override
    protected void handshake() {
        System.out.println("兩隊球員依次握手");
    }

    @Override
    protected void fight() {
        System.out.println("你一腳呀我一腳");
    }

    @Override
    protected void exit() {
        System.out.println("隊伍繞場一週致謝觀衆,裏皮憤怒立場");
    }

}

定義完抽象模板Game和具體的實現模板BoxingGame、FootballGame之後,我們就可以來模擬舉辦這兩場比賽了。

/**
 * @Descrtption Main
 * @Author luke
 * @Date 2019/11/20
 **/
public class Main {

    public static void main(String[] args) {
        //來一場真男人的比賽
        Game game = new BoxingGame();
        game.play();
        System.out.println("--------------------");
        //來一場男足比賽
        game = new FootballGame();
        game.play();
    }

}
用拳套觸碰
你一拳呀我一拳
運動員送往醫療室理療
觀衆退場,打掃場地
--------------------
兩隊球員依次握手
你一腳呀我一腳
隊伍繞場一週致謝觀衆,裏皮憤怒立場
觀衆退場,打掃場地

設計模式延伸-抽象類

在學習設計模式過程中,我們會經常的使用到抽象類和接口,對於抽象類我們是無法實例化的,例如對於Game這個抽象類,它只是定義一次抽象比賽的賽事,無法指定具體是什麼比賽。抽象類能夠去定義處理的流程,將具體的實現由子類去控制,可以達到封裝和解耦的效果,讓我們的代碼更具擴展性。設計模式能夠幫助我們當新的需求來臨的時候,代碼不需要做太大的修改,不會讓我們的代碼變得臃腫,難以維護。
假設我們現在需要舉辦一場籃球比賽,我們只需要增加一個具體模板類BasketballGame即可,客戶端不需要做任何改變,因爲客戶端依賴的是Game這個抽象類,而不是具體實現類,這就是抽象類或者說設計模式的意義,這種變與不變就是設計模式中的開閉原則,對擴展開放,對修改關閉。

使用場景

通過上面的介紹你也許已經知道了在哪些場景可以使用模板方法,能夠將多個子類的方法抽象成共有方法,並且會有邏輯相同的執行過程,並且這個過程是一個複雜、重要的方法,那麼就可以考慮使用模板方法。同時因爲抽象模板定義了固定的執行過程,所以一般情況下需要將模板方法定義爲final類型。

模式比較

在前面文章介紹的工廠方法的時候,我們定義了抽象工廠CarFactory。因爲建造車的過程是比較複雜的,無法通過一個簡單的new來構造出car對象,而這個負責的建造的過程又是一個具有固定步驟的過程,設計、購買材料、加工生產。你會驚訝發現這不就是模板方法嗎?沒錯,這裏的建造過程正是使用到了模板方法設計模式。隨着讀者不斷實踐模板方法你會發現,工廠方法往往會結合模板方法一塊使用。同時我們也需要區分他們之間的使用差異,工廠方法注重於怎麼構建出對象,而模板方法則注重於某個具有固定步驟的過程。

public abstract class CarFactory {

    public final Car createCar(){
        Car car = design();//設計
        buyMaterial(car);//購買材料
        working(car);//加工生產
        return car;
    }

    protected abstract Car design();

    protected abstract void buyMaterial(Car car);

    protected abstract void working(Car car);

}

java中使用到模板方法

1、spring 中對 Hibernate 的支持,將一些已經定好的方法封裝起來,比如開啓事務、獲取 Session、關閉 Session 等,程序員不重複寫那些已經規範好的代碼,直接丟一個實體就可以保存。
2、HttpServlet類提供了一個service()方法,這個方法調用七個do方法中的一個或幾個,完成對客戶端調用的響應。這些do方法需要由HttpServlet的具體子類提供,因此這是典型的模板方法模式。

我的公衆號

Alt

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章