本章源碼基於JDK1.7
模板方法模式的主要設計思想是定義一個算法框架,允許用子類重寫或者其它方式對算法框架內的某個步驟的具體實現進行修改。
本章內容已沖泡咖啡和茶作爲例子講解,咖啡和茶葉作爲飲料的一種有共通之處,首先燒水、然後沖泡咖啡或茶葉,最後將沖泡後的咖啡或茶葉水倒進杯子中。
我們可以將燒水行爲和將飲料倒進杯子行爲抽象出來,但是沖泡咖啡還是茶葉的話就必須要具體的去處理。
下面爲具體代碼實現
Drink.java
抽象父類Drink,其中boilWater和pourInCup是抽象出來的父類方法,由子類繼承,brew沖泡方法則根據沖泡咖啡還是茶葉具體由子類去決定。
Drink中的prepareRecipe是算法主幹方法,它決定了準備飲料步驟的算法邏輯,第一步燒水、第二步沖泡、第三步將飲料倒進杯子。
在Drink中同時也實現了一個鉤子方法hook,該鉤子方法能夠影響到算法主幹方法,子類方法通過重寫該鉤子方法來改變算法主幹方法。
public abstract class Drink {
//準備飲料
void prepareRecipe(){
boilWater();
brew();
if(hook()){
pourInCup();
}
}
//燒水
public void boilWater(){
System.out.println("燒水");
}
//沖泡
public abstract void brew();
//將飲料倒進杯子裏
public void pourInCup(){
System.out.println("倒飲料進杯子");
}
//鉤子方法
public boolean hook(){
return true;
}
}
Tea.java
茶葉類重寫飲料父類Drink的brew方法,實現沖泡茶葉的邏輯,並且重寫hook方法,改變了父類的算法主幹,沖泡完茶葉後並不將茶水倒入杯子中。
public class Tea extends Drink{
@Override
public void brew() {
System.out.println("沖泡茶葉");
}
//重寫父類Drink的鉤子方法,改變父類算法主幹邏輯
@Override
public boolean hook() {
return false;
}
}
Coffee.java
咖啡類繼承飲料父類Drink,重寫brew方法實現沖泡咖啡的具體邏輯
public class Coffee extends Drink{
@Override
public void brew() {
System.out.println("沖泡咖啡");
}
}
Test.java
分別實例化茶葉和咖啡,分別準備兩種飲料
public class Test {
public static void main(String[] args) {
Drink tea = new Tea();
tea.prepareRecipe();
System.out.println();
Drink coffee = new Coffee();
coffee.prepareRecipe();
}
}
運行結果
可以看到沖泡茶葉後並沒有倒進杯子中,而咖啡沖泡後會倒入杯子中,說明鉤子方法生效了,改變了主幹算法邏輯。
延伸擴展
jdk源碼中比較器其實也是一種模板方法模式,它的設計思想是定義一個算法主幹,然後通過傳入比較器或者實現實體的比較方法來對算法主幹的某個步驟進行具體實現。