設計模式 _第四招式_模版方法模式
阿新 • • 發佈:2018-11-07
一、定義
定義一個操作中的演算法框架,而將一些步驟延遲到子類中。使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。模版方法模式確實非常簡單,僅使用了Java的繼承機制,是一種應用非常廣泛的模式。
模版方法模式通用類圖如下:
AbstractClass叫做抽象模版,它的方法可以分為兩類:
- 基本方法:
基本方法也叫基本操作,是由子類實現的方法,並且在模版方法被呼叫。 - 模版方法:
可以有一個或幾個一般是一個具體的方法,也就是一個框架,實現對基本方法的排程,完成固定的邏輯。
二、程式碼演示
在類圖中還有一個角色:具體模版。ConcreteClass1和ConcreteClass2屬於具體模版,實現父類所定義的一個或多個抽象方法,也就是父類定義的基本方法在子類中得以實現。
- 抽象模版
public abstract class AbstractClass {
//基本方法
protected abstract void doSomething();
//基本方法
protected abstract void doAnything();
//模版方法
public void templateMethod(){
/**
*呼叫基本方法,完成相關的邏輯
*/
this.doAnything();
this.doSomething();
}
}
- 具體模版類
public class ConcreteClass1 extends AbstractClass {
//基本方法實現
@Override
protected void doAnything() {
//業務邏輯
System.out.println(" ConcreteClass1_doAnything業務邏輯");
}
@Override
protected void doSomething() {
//業務邏輯
System.out.println(" ConcreteClass1_doSomething業務邏輯" );
}
}
public class ConcreteClass2 extends AbstractClass {
//基本方法實現
@Override
protected void doAnything() {
//業務邏輯
System.out.println(" ConcreteClass2_doAnything業務邏輯");
}
@Override
protected void doSomething() {
//業務邏輯
System.out.println(" ConcreteClass2_doSomething業務邏輯");
}
}
- 場景類
public class Client {
public static void main(String args[]){
AbstractClass class1 = new ConcreteClass1();
AbstractClass class2 = new ConcreteClass2();
//呼叫模版方法
class1.templateMethod();
class2.templateMethod();
}
}
三、優點
- 封裝不變部分,擴充套件可變部分
把認為不變的部分的演算法封裝到父類實現,而可變部分則可以通過繼承來繼續擴充套件。 - 提取公共部分程式碼,便於維護
如果我們不抽取到父類中,任由這種散亂的程式碼發生,維護人員為了修正一個bug,需要找到所有類似的程式碼。 - 行為有父類控制,子類實現
基本方法是子類實現的,因此子類可以通過擴充套件的方式增加相應的功能,符合開閉原則。
四、缺點
按照我們的設計習慣,抽象類負責宣告最抽象、最一般的事物和方法,實現類具體的實現屬性和方法。但是模版設計模式卻顛倒了,抽象類中的部分抽象方法有子類實現,子類的執行結果影響父類的執行結果,這在複雜的專案中,回來來程式碼閱讀的難道。
五、應用場景
- 多個子類有共有的方法,且邏輯基本相同;
- 重要、複雜的演算法,可以把核心演算法設計為模版方法,周邊的相關細節功能則有各子類實現;
- 重構時,模版方法模式是一個經常使用的設計模式,把相同的程式碼抽取到父類中,然後通過鉤子函式約束其行為。
六、注意事項
- 為了防止惡意的操作,一般模版方法都加上final關鍵字,不允許被覆寫。
- 抽象模版中的基本方法儘量設計為protect型別,符合迪米特法則,不需要暴露的屬性或或方法儘量不要設定為public型別。實現類,儘量不要擴大父類中的訪問許可權。