模板方法模式
定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。 模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。通俗的說的就是有很多相同的步驟的,在某一些地方可能有一些差別適合於這種模式,例如想要泡一杯茶或者一杯咖啡,第一步都是將水煮沸,第二部是加入咖啡或者茶,第三部就是將飲料倒入杯子中,第四部就是加入各種調味料。其中第一步和第三部都是一樣的,這個就可以定義在基類,而第二步和第四步就是他們之間的差異就可以在具體的子類中去實現。下面就是代碼實現。
定義抽象基類,為所有子類提供一個算法框架
public abstract class RereshBaverage { /** * 制備飲料的模板方法 * 封裝了所有子類共同遵守的算法骨架 */ public final void prepreBvergeTemplage(){ //步驟一 將水煮沸 boilWater(); //步驟二 炮制飲料 brew(); //步驟三 將飲料倒入杯中 pourInCup(); //步驟四 加入調味料 addCondiments(); } /** * 基本方法,將水煮沸 這對所有子類而言是一個共同的行為,所以聲明為private,無需向子類開放 */ private void boilWater(){ System.out.println("將水煮沸"); } /** * 抽象的基本方法 泡制飲料 * 在算法框架中並不知道具體實現是什么樣子的,所以做成了抽象方法,並且由於我們需要在子類中可見,便於復寫而提供具體的實現所以將 * 權限設置為protected */ protected abstract void brew(); private void pourInCup(){ System.out.println("將飲料倒入杯中"); } /** * 加入調味料 */ protected abstract void addCondiments(); }
具體子類,提供了咖啡制備的具體實現
public class Coffee extends RereshBaverage { @Override protected void brew() { System.out.println("用沸水沖泡咖啡"); } @Override protected void addCondiments() { System.out.println("加入糖和牛奶"); } }
具體子類,提供了制備茶的具體實現
public class Tea extends RereshBaverage { @Override protected void brew() { System.out.println("用80 度的熱水浸泡茶葉5分鍾"); } @Override protected void addCondiments() { System.out.println("加入檸檬"); } }
測試類
public class RereshBaverageTest { public static void main(String[] args) { System.out.println("咖啡制備中。。。"); RereshBaverage coffee = new Coffee(); coffee.prepreBvergeTemplage(); System.out.println("咖啡制備完成! "); System.out.println("\n*********************"); System.out.println("茶制備中。。。"); RereshBaverage tea = new Tea(); tea.prepreBvergeTemplage(); System.out.println("茶制備完成!"); } }
運行結果:
如果我們希望喝到一杯black coffee或者喝到一杯純正的茶,就是不希望實現第四個步驟,那么將如何實現呢,如何做到個性化的擴展呢,這里就用到了一個鈎子方法。
改造基類方法,添加鈎子函數,如圖所示
子類茶重寫父類方法,實現掛載鈎子,如圖所示
測試和結果
茶的實現就少了加入檸檬的步驟。這就是鈎子函數的作用,他為我們在子類中提供了和更加的靈活性與選擇性決定算法的具體實現。
總結:
模板方法模式的實現要素:1.抽象基類 2.具體子類。在抽象基類中要提供一些具體的基本方法,對於各種不同的實現子類而言是相同的,具有共性的。還有一些抽象方法,是對於那些我們只知道具體原則,而不知道實現細節,需要將她延遲到子類實現的一些步驟。還有一些我們可選的鈎子函數。最后我們將基本方法,抽象方法和鈎子函數按照我們業務邏輯的需求匯總成一個模板方法,這就構成了我們的算法框架,模板方法必須聲明成final,不能被子類所復寫。
具體子類:1.實現基類中的抽象方法 2.覆蓋鈎子方法。
模板方法模式的適用場景:
(1)算法或操作遵循相似的邏輯
(2)重構時(把相同的代碼提取到父類中)
(3)重要復雜的算法,核心算法設計為模板方法
模板方法模式的優點:1.封裝性好 2.復用性好 3.屏蔽細節 4.便於維護
模板方法模式的缺點:繼承 java是一個單繼承的語言,設想在一個已有的系統當中大量的使用到了繼承,這個時候如果我們想要做一些重構,通過模板方法的模式抽取共性,因為我們的類已經出一個繼承層次的某個結構之中,再通過模板方法引入新的繼承的時候就會遇到困難。