一個最簡單的設計模式-模板方法

《Head First設計模式》已經讀了不止一遍,可是始終沒有進行系統的進行總結。因此近期開始總結設計模式相關的知識,從模板方法模式開始,由於是一個我認爲是最簡單的設計模式。(推薦視頻資源23個設計模式java

提出&解決問題

提出問題程序員

實現製做咖啡功能。且製做咖啡須要四個步驟 :算法

  1. 燒水
  2. 沖泡咖啡
  3. 倒入杯中
  4. 加糖

代碼實現設計模式

/**
 * 一杯加糖咖啡
 *
 * @author Jann Lee
 * @date 2019-07-14 18:37
 */
public class Coffee {

    /**
     * 製做一杯加糖咖啡
     */
    public void prepareRecipe() {
        boilWater();
        steepTeaBag();
        portInCup();
        addLemon();
    }

    /**
     * step1: 燒水
     */
    private void boilWater() {
        System.out.println("燒水...");
    }

    /**
     * step2:沖泡咖啡
     */
    private void steepTeaBag() {
        System.out.println("沖泡咖啡...");
    }

    /**
     * step3: 倒入杯中
     */
    private void portInCup() {
        System.out.println("倒入杯中...");
    }

    /**
     * step4: 加糖
     */
    private void addLemon() {
        System.out.println("加糖...");
    }

再次提出問題此時此刻我須要一杯檸檬茶呢?【燒水,沖泡茶包,倒入杯中,加檸檬】cookie

這個問題固然很簡單,咱們只須要如法炮製便可。框架

public class Tea {

    /**
     * 製做一杯檸檬茶
     */
    public void prepareRecipe(){
        boilWater();
        brewCoffeeGrinds();
        portInCup();
        addSugarAndMilk();
    }

    /**
     * step1: 燒水
     */
    private void boilWater() {
        System.out.println("燒水...");
    }

    /**
     * step2:沖泡咖啡
     */
    private void brewCoffeeGrinds() {
        System.out.println("沖泡茶包...");
    }

    /**
     * step3: 倒入杯中
     */
    private void portInCup() {
        System.out.println("倒入杯中...");
    }

    /**
     * step4: 加檸檬
     */
    private void addSugarAndMilk() {
        System.out.println("加入檸檬片...");
    }
}

思考ide

​ 若是此時咱們又須要一杯不加檸檬的茶,加奶的咖啡...,固然咱們能夠按照上面方式從新依次實現便可。可是若是你是一個有經驗的程序員,或者你學習過設計模式。你可能會發現以上功能實現的步驟/流程固定,當需求發生變化時,只有小部分步驟有所改變學習

優化代碼

根據面向對象程序的特色,既抽象,封裝,繼承,多態。咱們能夠對代碼進行抽象,將公共代碼提取到基類。咱們將咖啡和茶抽象成咖啡因飲料,將其中相同的兩步,燒水和倒入杯中再父類中實現,將沖泡和添加調料延遲到子類。優化

  1. 定義一個基類
public abstract class CafeineBeverage {
    /**
     * 製做一杯咖啡因飲料
     */
    public void prepareRecipe() {
        boilWater();
        brew();
        portInCup();
        addCondiments();
    }

    /**
     * step1: 燒水
     */
    private void boilWater() {
        System.out.println("燒水...");
    }

    /**
     * step2:沖泡
     */
    protected abstract void brew();

    /**
     * step3: 入杯中
     */
    private void portInCup() {
        System.out.println("倒入杯中...");
    }

    /**
     * step4: 加調料
     */
    protected abstract void addCondiments();
}
// 一杯加糖咖啡
public class CoffeeBeverage extends CafeineBeverage{

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

    @Override
    protected void addCondiments() {
        System.out.println("加糖...");
    }
}
// 一杯檸檬茶
public class TeaBeverage extends CafeineBeverage {
    @Override
    protected void brew() {
        System.out.println("沖泡茶包...");
    }

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

模板方法模式

若是按以上方式對代碼進行了優化,其實就實現了模板方法模式。一下是模板方法模式相關概念。網站

動機

  • 在軟件構建過程當中,對於某一項任務,它經常有穩定的總體操做結構,可是各個子步驟卻有不少改變的需求,或者因爲固有的緣由(好比框架與應用之間的關係)而沒法和任務的總體結構同時實現
  • 如何在肯定穩定的操做結構的前提下,來靈活應對各個子步驟的變化或者晚期實現需求?

定義

定義一個操做中算法的骨架(穩定),而將一些步驟延遲(變化)到子類。Template Method使得子類能夠不改變(複用)一個算法的結構,便可從新定義(override)該算法的特定步驟。

要點總結

  • Template Method是一種很是基礎性的設計模式,在面向對象系統中,有着大量的應用。他用最簡潔的機制(抽象類的多態,爲不少應用框架提供了靈活的擴展點,是代碼複用方面最基本實現結構)
  • 除了能夠靈活應對子步驟的變化外,「不要調用我,讓我來調用你」的反向控制結構是Template Method的典型應用
  • 在具體實現方面,被Template Method調用得虛方法能夠有實現,也能夠沒有實現(抽象方法),但通常推薦設置爲protected方法

類圖:

我的博客網站(正在建設中)

相關文章
相關標籤/搜索