設計模式 - 模板方法模式

去銀行辦業務,咱們能夠總結爲取號、等號、辦業務,區號和等號每一個人沒什麼不一樣;但業務就有不一樣,有人存款,有人取款。java

對於這種一套業務流程中,各個模塊大同小異的狀況,定義出業務流程的基本框架,而將一些步驟延遲到子類中,稱爲模板方法模式。算法

意圖

定義一個操做中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類能夠不改變一個算法的結構便可重定義該算法的某些特定步驟。框架

示例

該模式比較簡單,直接在代碼中進行部分說明ide

假設泡咖啡和沏茶的步驟能夠抽象爲以下:測試

  1. 將水煮沸
  2. 泡製飲料(咖啡:沸水沖泡 茶:溫水浸泡)
  3. 將飲料倒入杯中
  4. 加入調味料(咖啡:加入牛奶和糖 茶: 加入檸檬)

抽象骨架示例code

package com.dotleo.template;

/**
 * 飲料製做模擬
 *
 * 抽象基類,爲全部子類提供一個算法框架
 *
 * 思想:
 * 子類能夠改變父類中可變的邏輯結構,但不能改變總體結構
 *
 * 步驟:
 * 定義模板方法,模板方法使用非private修飾,最好用public修飾,保證子類能夠在任何地方使用;使用final修飾,避免了子類的複寫
 * 將統一的方法實現,並用private修飾,避免子類複寫;將不統一的方法定義爲抽象方法,並用非private修飾,子類複寫能夠實現不一樣的功能
 *
 * @author LiuFei
 * @create 2017-12-03 17:20
 */
public abstract class RefreshBeverage {

    /**
     * 紙杯飲料的模板方法
     * 封裝了全部子類共同遵循的算法框架
     */
    public final void prepareBeverageTemplate() {
        // 1. 將水煮沸
        boilWater();
        // 2. 泡製飲料
        brew();
        // 3. 將飲料倒入杯中
        pourInCup();
        // 4. 加入調味料
        addCondiments();
    }

    /**
     * 將水煮沸(統一方法,實現)
     */
    private void boilWater() {
        System.out.println("將水煮沸");
    }

    /**
     * 泡製飲料(不統一方法,抽象)
     */
    protected abstract void brew();

    /**
     * 將飲料倒入杯中(統一方法,實現)
     */
    private void pourInCup() {
        System.out.println("將飲料倒入杯中");
    }

    /**
     * 加入調味料(不統一方法,抽象)
     */
    protected abstract void addCondiments();


}

模擬製做咖啡圖片

package com.dotleo.template;

/**
 * 模擬製做咖啡
 *
 * @author LiuFei
 * @create 2017-12-03 17:42
 */
public class Coffee extends RefreshBeverage {
    @Override
    protected void brew() {
        System.out.println("用沸水沖泡咖啡");
    }

    @Override
    protected void addCondiments() {
        System.out.println("加入牛奶和糖");
    }
}

模擬製做檸檬茶it

package com.dotleo.template;

/**
 * 模擬製做檸檬茶
 *
 * @author LiuFei
 * @create 2017-12-03 17:48
 */
public class Tea extends RefreshBeverage {
    @Override
    protected void brew() {
        System.out.println("用溫水浸泡茶葉5分鐘");
    }

    @Override
    protected void addCondiments() {
        System.out.println("加入檸檬");
    }
}

測試類模板

package com.dotleo.template;

/**
 * @author LiuFei
 * @create 2017-12-03 17:45
 */
public class RefreshBeverageTest {

    public static void main(String[] args) {

        // 製備咖啡
        System.out.println("製備咖啡...");
        RefreshBeverage coffeeRefreshBeverage = new Coffee();
        coffeeRefreshBeverage.prepareBeverageTemplate();
        System.out.println("咖啡好了!");

        System.out.println("\n======================================================\n");

        // 製備檸檬茶
        System.out.println("製備檸檬茶...");
        RefreshBeverage teaRefreshBeverage = new Tea();
        teaRefreshBeverage.prepareBeverageTemplate();
        System.out.println("檸檬茶好了!");
    }
}

測試結果class

輸入圖片說明

優缺點

優勢:

  1. 封裝不變部分,擴展可變部分。
  2. 提取公共代碼,便於維護。
  3. 行爲由父類控制,子類實現。

缺點:

  1. 每個不一樣的實現都須要一個子類來實現,致使類的個數增長,使得系統更加龐大。

使用場景

  1. 有多個子類共有的方法,且邏輯相同。
  2. 重要的、複雜的方法,能夠考慮做爲模板方法。

注意事項

  1. 爲防止惡意操做,通常模板方法都加上 final 關鍵詞。
  2. 若是骨架中有不想讓子類重寫的方法,可使用 private 修飾
相關文章
相關標籤/搜索