定義一個操做中的算法的框架,而將一些步驟的實現延遲到子類中,使得子類能夠不改變一個算法的結構便可重定義該算法的某些特定步驟。java
使用模板方法模式製造兩款汽車。定義汽車必須有的特質:可以發動,鳴笛和中止,不一樣型號的汽車實現不一樣。汽車生產完成後須要對汽車的質量進行檢驗,測試汽車的全部功能。算法
抽象汽車模型(抽象汽車類)框架
public abstract class AbstractCar { // 汽車能夠發動,發動方式不一樣,須要在實現類裏實現 public abstract void start(); // 汽車能夠鳴笛,但聲音不一樣,須要在實現類裏實現 public abstract void alarm(); // 汽車能夠熄火,中止方式也不一樣,須要在實現類裏實現 public abstract void stop(); // 測試汽車的質量,操做步驟同樣,先測試啓動,再測試喇叭,最後測試熄火 public void run() { // 發動汽車 this.start(); // 按喇叭 this.alarm(); // 中止汽車 this.stop(); } }
兩種不一樣型號的汽車(汽車實現類)測試
public class CarOne extends AbstractCar { // 發動C1型號的汽車 public abstract void start() { System.out.println("手搖啓動C1型號的汽車"); } // C1型號的汽車鳴笛 public abstract void alarm() { System.out.println("C1型號的汽車鳴笛滴滴"); } // 中止C1型號的汽車 public abstract void stop() { System.out.println("鑰匙關閉C1型號的汽車"); } } public class CarTwo extends AbstractCar { // 發動C2型號的汽車 public abstract void start() { System.out.println("電子啓動C2型號的汽車"); } // C2型號的汽車鳴笛 public abstract void alarm() { System.out.println("C1型號的汽車鳴笛嗶嗶"); } // 中止C2型號的汽車 public abstract void stop() { System.out.println("電子關閉C1型號的汽車"); } }
測試汽車(場景類)this
public class Client { public static void main(String[] args) { CarOne carOne = new CarOne(); carOne.run(); CarTwo carTwo = new CarTwo(); carTwo.run(); } }
模板方法模式實現簡單,僅僅使用了java的繼承機制。以上述例子爲例,其中AbstractCar叫作抽象模板,它的方法分爲兩類:設計
- 基本方法:由子類實現的方法,並在模板方法中被調用。
- 模板方法:數量不限,通常是一個具體的方法,也就是定義中所說的算法,它實現對基本方法的調度,完成固定的邏輯。
CarOne和CarTwo叫作具體模板,實現抽象模板所定義的基本方法。code
注意:抽象模板中的基本方法儘可能設計爲
protected
類型,不須要i暴露的屬性或方法儘可能不要設置爲protected
類型,實現類非必要的狀況,儘可能不擴大父類中的訪問權限。繼承
在上述造車的基礎上實現,C1型車能夠控制是否鳴笛,C2型車不鳴笛。鉤子
擴展後的汽車抽象模型模板
public abstract class AbstractCar { // 汽車能夠發動,發動方式不一樣,須要在實現類裏實現 protected abstract void start(); // 汽車能夠鳴笛,但聲音不一樣,須要在實現類裏實現 protected abstract void alarm(); // 汽車能夠熄火,中止方式也不一樣,須要在實現類裏實現 protected abstract void stop(); // 測試汽車的質量,操做步驟同樣,先測試啓動,再測試喇叭,最後測試熄火 public final void run() { // 發動汽車 this.start(); if (this.isAlarm()) { // 按喇叭 this.alarm(); } // 中止汽車 this.stop(); } // 鉤子方法,默認喇叭會響 protected boolean isAlarm() { return true; } }
擴展後的汽車實現類
public class CarOne extends AbstractCar { // C1汽車要能夠鳴笛 private boolean alarmFlag = true; // 發動C1型號的汽車 protected abstract void start() { System.out.println("手搖啓動C1型號的汽車"); } // C1型號的汽車鳴笛 protected abstract void alarm() { System.out.println("C1型號的汽車鳴笛滴滴"); } // 中止C1型號的汽車 protected abstract void stop() { System.out.println("鑰匙關閉C1型號的汽車"); } // 是否鳴笛由駕駛員控制 public void setAlarm(boolean isAlarm) { this.isAlarm = isAlarm; } } public class CarTwo extends AbstractCar { // 發動C2型號的汽車 protected abstract void start() { System.out.println("電子啓動C2型號的汽車"); } // C2型號的汽車鳴笛 protected abstract void alarm() { System.out.println("C1型號的汽車鳴笛嗶嗶"); } // 中止C2型號的汽車 protected abstract void stop() { System.out.println("電子關閉C1型號的汽車"); } // C2汽車不能鳴笛 protected boolean isAlarm() { return false; } }
C1汽車由駕駛員控制是否鳴笛,抽象類中的
isAlarm
方法的返回值影響了run
方法的執行結果,即外界條件的改變會影響到模板方法的執行,該方法就叫作鉤子方法。