如何使用“模板設計模式”

在瞭解“模板設計模式”之前要先了解關於抽象類的相關概念:

  • 抽象類的定義與使用
    a)定義:抽象類只是比普通類多了一些抽象方法
    b)抽象方法:只聲名而未實現的方法(沒有方法體),抽象方法必須使用abstract關鍵字類定義。並且抽象方法所在的類也一定要使用abstract來定義

  • 抽象類的使用原則
    a)所有抽象類必須有子類
    b)抽象類的子類必須覆寫抽象類的所有抽象方法
    c)抽象類無法直接創建實例化對象,需要通過子類向上轉型爲其實例化

  • 抽象類的相關約定
    a)抽象類一定存在構造方法,子類也一定遵循對象實例化流程。先調用父類構造,再調用子類構造
    b)抽象類可以沒有任何抽象方法,但此時仍然不能直接創建實例化對象
    c)final與abract,private與abract不能同時出現

以上是關於抽象類的一些基本概念
關於抽象類的詳細內容可以參考:https://mp.csdn.net/postedit/103091095

如果現在需要實現*“沖泡牛奶和沖泡果汁”*的功能,用普通方法可能會這樣實現:

class Milk{
    void prepareRecipe(){
        boilWater();
        brewMilk();
        pourIncup();
        addSugar();
    }
    void boilWater(){
        System.out.println("boil water");
    }
    void brewCoffee(){
        System.out.println("brew milk");
    }
    void pourIncup(){
        System.out.println("pour in cup");
    }
    void addSugar(){
        System.out.println("add suger");
    }
}

class Juice{
    void prepareRecipe(){
        boilWater();
        brewJuice();
        pourIncup();
        addLemon();
    }
    void boilWater(){
        System.out.println("boil water");
    }
    void brewJuice(){
        System.out.println("brew juice");
    }
    void pourIncup(){
        System.out.println("pour in cup");
    }
    void addLemon(){
        System.out.println("add lemon");
    }
}

public class Drink {
    public static void main(String[] args) {
        Milk milk = new Milk();
        milk.prepareRecipe();
        Juice juice = new Juice();
        juice.prepareRecipe();
    }
}

如上述代碼所示,這樣寫下來重複代碼很多,代碼複用率很少,程序的可擴展性也不好,如果想要在增加沖泡其他類似東西,相似的代碼又得重新寫一遍,因此使用“模板設計模式”對以上代碼進行修改.

那麼什麼是“模板設計模式”呢?
模板(模板方法)設計模式:
基於抽象類,在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。
模板模式可以使得子類在不改變算法的前提下,重新定義算法中的某些步驟

這樣的說法有點抽象,實際上就是將核心部分的算法進行封裝,讓子類結合自己所需繼承或修改相應的方法,這樣就使得代碼複用率高,邏輯性強,彈性高

結合到“沖泡牛奶和沖泡果汁”這個例子來講,就是把沖泡這兩樣東西都要經歷的過程(例如:boilwater(),pourIncup())提煉出來,將兩者不同的部分(例如:addLemon()/addsuger())用抽象方法實現,這樣子類繼承的時候就可以根據自己的需求來覆寫相應的方法,代碼複用率大大提高。

那麼如果是一個飲品店使用到上述的方法時,可能會面臨有的顧客想加輔料,而有的顧客不想加相應的輔料,此時就要根據顧客的需求來決定是否加輔料,所以我們引進了
鉤子方法,根據需求選擇是否掛鉤,意思就是需要加輔料的時候才加相應輔料。

以上內容的實現代碼如下所示:

abstract class Moudle{
    final void prepareRecipe(){
        boilWater();
        brewSomething();
        pourIncup();
        if(custmersWantCondiments()) {
            addSomething();
        }
    }

    final void boilWater() {
        System.out.println("boil water");
    }
    abstract void brewSomething();
    private void pourIncup() {
        System.out.println("pour in cup");
    }
    abstract void addSomething();
    //鉤子方法
    boolean custmersWantCondiments(){
        return true;
    }
}
class Milk1 extends Moudle{
    @Override
    void brewSomething() {
        System.out.println("brew milk");
    }
    @Override
    void addSomething() {
        System.out.println("add suger");
    }
    boolean custmersWantCondiments() {
        System.out.println("do you need some suger ? y/n");
        String result = getUserInfo();
        if(result.equals("y") ){
            return true;
        }else {
            return false;
        }
    }
    private String getUserInfo() {
        Scanner scanner = new Scanner(System.in);
        String info = scanner.next();
        return info;
         }
   }
class Juice extends Moudle{
    @Override
    void brewSomething() {
        System.out.println("brew juice");
    }
    @Override
    void addSomething() {
        System.out.println("add leamon");
    }
}
public class DrinkMoudle {
    public static void main(String[] args) {
        Milk1 milk = new Milk1();
        milk.prepareRecipe();
        Juice1 juice = new Juice1();
        juice.prepareRecipe();
  
    }
}

設計模式的核心原則是開閉原則
開閉原則(OCP):一個軟件實體如類,模塊或函數應該對擴展開放,對修改關閉
上述的模板設計模式就遵循了此原則,對於核心的方法用final修飾,這樣就保障了子類可以使用但不可以修改,提高了安全性

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