1. 程式人生 > 實用技巧 >設計模式之模板設計模式

設計模式之模板設計模式

模板設計模式—基於抽象類的,核心是封裝演算法

  • 模板方法定義了一個演算法的步驟,並允許子類為一個或多個步驟提供具體實現
  • 模板(模板方法)模式(Servlet、AQS)
    • 在一個方法中定義一個演算法的骨架,並將一些具體步驟延遲到子類中實現。
    • 模板模式使得子類可以在不改變演算法結構的基礎上,重新具體定義演算法中的某些步驟

講模板設計模式之前,我們用程式碼來實現咖啡和茶製作的類:

class Coffee {    
    /*   
     * 咖啡沖泡法(演算法)     
    */    
    void prepareRecipe() {        
        boilWater();        
        brewCoffeeGrings();        
        pourInCup();        
        addSugarAndMilk();    
    }       
    public void boilWater() {        
        System.out.println("將水煮沸");    
    } 
    public void brewCoffeeGrings() {        
        System.out.println("沖泡咖啡");    
    }  
    public void pourInCup() {        
        System.out.println("把咖啡倒進杯子中");    
    }
    public void addSugarAndMilk() {        
        System.out.println("加糖和牛奶");    
    } 
}

class Tea {
/*
* 沖泡茶法(演算法)
*/
void prepareRecipe() {
boilWater();
steepTeaBag();
pourInCup();
addLemon();
}
public void boilWater() {
System.out.println("將水煮沸");
}
public void steepTeaBag() {
System.out.println("浸泡茶葉");
}
public void pourInCup() {
System.out.println("把茶倒進杯子中");
}
public void addLemon() {
System.out.println("加檸檬");
}
}
class Test {
public static void main(String[] agrs) {
Coffee coffee = new Coffee();
Tea tea = new Tea();
coffee.prepareRecipe();
tea.prepareRecipe();
}
}

我們在這兩個類中發現了重複程式碼,因此我們需要重新理一下我們的設計。

  • 既然茶和咖啡是如此的相似,因此我們應該將共同的部分抽取出來,放進一個基類中。
  • 從沖泡法入手。觀察咖啡和茶的沖泡法我們會發現,兩種沖泡法都採用了相同的演算法:
    • 將水煮沸
    • 用熱水泡飲料
    • 把飲料倒進杯子
    • 在飲料內加入適當的調料

實際上,浸泡(steep)和沖泡(brew)差異並不大。因此我們給它一個新的方法名稱brew(),這樣我們無論沖泡的是何種飲 料都可以使用這個方法。同樣的,加糖、牛奶還是檸檬也很相似,都是在飲料中加入其它調料,因此我們也給它一 個通用名稱addCondiments()。

/** 
 * 咖啡因飲料是一個抽象類 
**/ 
abstract class CaffeineBeverage {    
    /**
     * 現在用同一個prepareRecipe()方法處理茶和咖啡。     
     * 宣告為final的原因是我們不希望子類覆蓋這個方法!     
    **/    
    final void prepareRecipe() {        
        boilWater();        
        brew();        
        pourInCup();        
        addCondiments();   
    }
     /**     
      * 咖啡和茶處理這些方法不同,因此這兩個方法必須被宣告為抽象,留給子類實現     
     **/    
    abstract void brew();    
    abstract void addCondiments();
void boilWater() {        
     System.out.println("將水煮沸");    
}
void pourInCup() {        
     System.out.println("把飲料倒進杯子中");    
} 

}

class Coffee extends CaffeineBeverage {
public void brew() {
System.out.println("沖泡咖啡");
}
public void addCondiments() {
System.out.println("加糖和牛奶");
}
}

class Tea extends CaffeineBeverage {
public void brew() {
System.out.println("浸泡茶葉");
}
public void addCondiments() {
System.out.println("加檸檬");
}
}
class Test {
public static void main(String[] agrs) {
CaffeineBeverage coffee = new Coffee();
CaffeineBeverage tea = new Tea();
coffee.prepareRecipe();
tea.prepareRecipe();
}
}

模板方法定義了一個演算法的步驟,並允許子類為一個或者多個步驟提供具體實現

在模板設計模式下還有一種鉤子用法

鉤子方法是一類"預設不做事的方法" ,子類可以視情況決定要不要覆蓋它們。
比如說,顧客點杯咖啡時,可以選擇加不加牛奶或者糖!!!

import java.util.Scanner;

/**

  • 咖啡因飲料是一個抽象類
    /
    abstract class CaffeineBeverage {
    /

    • 現在用同一個prepareRecipe()方法處理茶和咖啡。
    • 宣告為final的原因是我們不希望子類覆蓋這個方法!
      /
      final void prepareRecipe() {
      boilWater();
      brew();
      pourInCup();
      if(customerWantsCondiments())
      addCondiments();
      }
      /
    • 咖啡和茶處理這些方法不同,因此這兩個方法必須被宣告為抽象,留給子類實現
      **/
      abstract void brew();
      abstract void addCondiments();

    void boilWater() {
    System.out.println("將水煮沸");
    }
    void pourInCup() {
    System.out.println("把飲料倒進杯子中");
    }
    boolean customerWantsCondiments() {
    return true;
    }
    }

class Coffee extends CaffeineBeverage {
public void brew() {
System.out.println("沖泡咖啡");
}
public void addCondiments() {
System.out.println("加糖和牛奶");
}

 /**  
  * 子類覆寫了鉤子函式,實現自定義功能   
 **/ 
boolean customerWantsCondiments() {
    String result = getUserInput();
    if(result.equals("y"))
        return true;
    else
        return false;
}    
private String getUserInput() {
    System.out.println("您想要在咖啡中加入牛奶或糖嗎(y/n)?");
    Scanner scanner = new Scanner(System.in);
    String str = scanner.nextLine();
    return str;
}

}

class Tea extends CaffeineBeverage {
public void brew() {
System.out.println("浸泡茶葉");
}
public void addCondiments() {
System.out.println("加檸檬");
}
}
class Test {
public static void main(String[] agrs) {
CaffeineBeverage coffee = new Coffee();
CaffeineBeverage tea = new Tea();
coffee.prepareRecipe();
tea.prepareRecipe();
}
}


轉載:https://blog.csdn.net/sifanchao/article/details/83418339