概述算法
模板方法模式在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類能夠在不改變算法結構的狀況下,從新定義算法中的某些步驟。框架
類結構圖ide
解決問題測試
模板方法就是提供一個算法框架,框架裏面的步驟有些是父類已經定好的,有些須要子類本身實現。至關於要去辦一件事情,行動的流程已經定好了,但有些步驟須要本身去作,而有些步驟可能別人幫咱們作了。網站
就拿建網站來講,通常的程序是購買域名-->購買空間-->上傳網站-->備案-->審覈,每一個網站的建立必須通過這樣的固定程序,但除了審覈不用建站者關心,其餘的步驟都要建站者本身去完成。spa
應用實例orm
如今咱們不少家庭都有了豆漿機,豆漿的養分價值不用我多說了。繼承
製做豆漿的程序簡單點來講就是ip
選材--->添加配料--->浸泡--->放到豆漿機打碎,經過添加不一樣的配料,能夠製做出不一樣口味的豆漿,可是選材、浸泡和放到豆漿機打碎這幾個步驟對於製做每種口味的豆漿都是同樣的。ci
代碼
//豆漿類,抽象類 public abstract class SoyaMilk { //這是模板方法,用final修飾,不容許子類覆蓋。模板方法定義了製做豆漿的程序 final void prepareRecipe(){ selectMaterial(); addCondiments(); soak(); beat(); } //選材方法,選擇黃豆 void selectMaterial(){ System.out.println("第一步、選擇好了新鮮黃豆"); } //能夠添加不一樣的配料,在這裏設置爲抽象方法,子類必須實現 abstract void addCondiments(); //浸泡 void soak(){ System.out.println("第三步、黃豆和配料開始浸泡,大概須要5個小時"); } //放到豆漿機打碎 void beat(){ System.out.println("第四步、黃豆的配料放到豆漿機打碎"); } }
//紅棗豆漿 public class ReddatesSoyaMilk extends SoyaMilk{ //實現父類的添加配料方法 @Override void addCondiments() { System.out.println("第二步、添加紅棗配料"); } } //核桃豆漿 public class NutSoyaMilk extends SoyaMilk{ //實現父類的添加配料方法 @Override void addCondiments() { System.out.println("第二步、添加核桃配料"); } }
測試製做豆漿
public class SoyaMilkTest { public static void main(String[] args){ //製做紅棗豆漿 System.out.println(); System.out.println("-----製做紅棗豆漿步驟-------"); SoyaMilk reddatesSoyaMilk = new ReddatesSoyaMilk(); reddatesSoyaMilk.prepareRecipe(); //製做核桃豆漿 System.out.println(); System.out.println("-----製做核桃豆漿步驟-------"); SoyaMilk nutSoyaMilk = new NutSoyaMilk(); nutSoyaMilk.prepareRecipe(); } }
運行結果
鉤子方法
在模板方法模式的父類中,咱們能夠定義一個方法,它默認不作任何事,子類能夠視狀況要不要覆蓋它,該方法稱爲「鉤子」。咱們仍是用上面作豆漿的例子來說解。
//這是模板方法,用final修飾,不容許子類覆蓋。模板方法定義了製做豆漿的程序 final void prepareRecipe(){ selectMaterial(); //判斷是否添加配料 if(customerWantsCondiments()){ addCondiments(); } soak(); beat(); } //鉤子方法,是否添加配料 boolean customerWantsCondiments(){ return true; }
//製做純豆漿,不添加任何配料 public class PureSoyaMilk extends SoyaMilkWithHook{ @Override void addCondiments() { } //覆蓋鉤子方法,不添加配料 @Override boolean customerWantsCondiments(){ return false; } }
//測試類: public class PureSoyaMilkTest { public static void main(String[] args){ //製做純豆漿 System.out.println(); System.out.println("-----製做純豆漿步驟-------"); SoyaMilkWithHook pureSoyaMilk = new PureSoyaMilk(); pureSoyaMilk.prepareRecipe(); } }
運行結果:
優缺點
1
優勢
(1)、算法只存在於一個地方,也就是在父類中,容易修改。須要修改算法時,只要修改父類的模板方法或者已經實現的某些步驟,子類就會繼承這些修改。
(2)、實現了最大化代碼複用。父類的模板方法和已實現的某些步驟會被子類繼承而直接使用。
(3)、既統一了算法,也提供了很大的靈活性。父類的模板方法確保了算法的結構保持不變,同時由子類提供部分步驟的實現。
(4)、提供了一個基本框架,容易擴展子類。模板方法有框架控制如何作事情,而由使用框架的人指定框架算法中每一個步驟的細節。子類只要繼承父類,實現抽象方法,就能夠使用父類的算法。
2
缺點
模板方法使用繼承方式複用代碼,若是要在基本算法裏面增長一個步驟,而該步驟是抽象的話,每一個子類都要修改代碼,實現這個步驟。