1. 程式人生 > 程式設計 >23種設計模式之模板方法模式

23種設計模式之模板方法模式

1、定義

定義一個操作中的演演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個演演算法的結構即可重定義改演演算法的某些特定步驟。模板方法模式是一種基於繼承的程式碼複用技術。

2、模式結構

模板方法模式由兩部分組成:

  • AbstractClass(抽象類):在抽象類中定義了一系列基本操作,這些基本操作可以是具體的,也可以是抽象的,每一個基本操作對應演演算法的一個步驟,在其子類中可以重定義或實現這些步驟,同時,在抽象類實現了模板方法,用於定義一個演演算法的框架,模板方法不僅可以呼叫在抽象類中實現的基本方法,也可以呼叫在抽象的子類中實現的基本方法,還可以呼叫其他物件的方法。
  • 模板方法(Template Method):定義了演演算法的骨架,按某種順序呼叫其包含的基本方法。一般以final修飾,不允許子類重寫。
  • 基本方法是實現演演算法各個步驟的方法,是模板方法的組成部分。基本方法分為三種。
  • 抽象方法(Abstract Method):父類中只宣告但不加以實現,而是定義好規範,然後由它的子類去實現。
  • 具體方法(Concrete Method):由抽象類宣告並加以實現,其子類可以進行重寫或者直接繼承。
  • 鉤子方法(Hook Method):由抽象類宣告並加以實現。但是子類可以去擴充套件,子類可以通過擴充套件鉤子方法來影響模板方法的邏輯。
  • ConcreteClass(具體子類):它是抽象類的子類,用於實現在父類中宣告的抽象基本操作以完成子類特定演演算法的步驟,也可以覆蓋在父類中已經實現的具體操作。

3、例項

3.1 豆漿類

public abstract class SoyMilk {

    public final void make() {
        select();
        if (customerWantCondiments()) {
            addCondiments();
        }
        soak();
        beat();
    }

    public void select() {
        System.out.println("選擇上好的新鮮黃豆。");
    }

    public abstract void addCondiments();

    public void soak
() { System.out.println("浸泡三小時原料。"); } public void beat() { System.out.println("放入到豆漿機打碎。"); } // 鉤子方法,決定是否需要新增配料 protected boolean customerWantCondiments() { return true; } } 複製程式碼

3.2 具體豆漿類

public class AlmondSoyMilk extends SoyMilk {
    
    @Override
    public void addCondiments() {
        System.out.println("加入上好的杏仁。");
    }
}
複製程式碼
public class WalnutSoyMilk extends SoyMilk {
    
    @Override
    public void addCondiments() {
        System.out.println("加入上好的核桃。");
    }
}
複製程式碼
public class OriginalSoyMilk extends SoyMilk {
    
    @Override
    public void addCondiments() {}
    
    @Override
    protected boolean customerWantCondiments() {
        return false;
    }
}
複製程式碼

3.3 客戶端呼叫

public class Client {

    public static void main(String[] args) {
        
        System.out.println("------製作杏仁豆漿------");
        SoyMilk almondSoyMilk = new AlmondSoyMilk();
        almondSoyMilk.make();
        
        System.out.println("------製作核桃豆漿------");
        SoyMilk walnutSoyMilk = new WalnutSoyMilk();
        walnutSoyMilk.make();
        
        System.out.println("------製作原味豆漿------");
        SoyMilk originalSoyMilk = new OriginalSoyMilk();
        originalSoyMilk.make();
    }
}
複製程式碼

4、適用場景

  • 一次性實現一個演演算法的不變部分,並將可變的行為留給子類來實現。
  • 各子類中公共的行為應被提取出來並集中到一個公共父類中以避免程式碼重複。
  • 控制子類擴充套件。模板方法只在特定點呼叫“hook”操作,這樣就只允許在這些點擴充套件。

5、在Spring中的應用

6、優缺點

6.1 優點
  • 可以將公共程式碼行為進行提取,以達到複用的目的。
  • 子類實現演演算法的某些細節,有助於演演算法的擴充套件。
  • 可實現一種反向控制結構,通過子類覆蓋父類的鉤子方法來決定某一個特定步驟是否需要執行。
6.2 缺點
  • 通過繼承實現程式碼複用來改變演演算法,使得靈活度會降低。
  • 子類的執行影響父類的結果,增加程式碼閱讀難度。

特別宣告:1、如若文中有錯之處,歡迎大神指出。 2、文章是參考網上一些大神的文章,自己整理出來的,如若有侵權,可聯絡我刪除。