模板方法模式(Template Method Pattern)

意圖

在一個方法中定義一個算法得骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些步驟。

動機

在設計一個系統時,明確了算法所需的關鍵步驟,而且確定了這些步驟的執行順序,但某些步驟的具體實現還未知或需依賴於具體的環境。我們可以在父類中把明確的算法步驟定義爲模板方法,而未知具體實現部分延遲到子類中實現。

適用性

模板方法模式通常適用於以下場景:

  • 算法的整體步驟很固定,但其中個別部分易變時,這時候可以使用模板方法模式,將容易變的部分抽象出來,在子類中實現。
  • 當多個子類存在公共的行爲時,可以將其提取出來並集中到一個公共父類中以避免代碼重複。首先,要識別現有代碼中的不同之處,並且將不同之處分離爲新的操作。最後,用一個調用這些新的操作的模板方法來替換這些不同的代碼。
  • 當需要控制子類的擴展時,模板方法只在特定點調用鉤子操作,這樣就只允許在這些點進行擴展。

結構

模板方法模式的主要角色有:

  • 抽象類(AbstractClass):定義模板方法,給出一個算法的輪廓和骨架。它由一個模板方法和若干個基本方法構成。
  • 具體子類(ConcreteClass):實現父類中所定義的抽象方法和選擇性實現鉤子方法。

實現

// 抽象類
public abstract class AbstractClass {
	// 模板方法,定義了一系列的邏輯步驟,每個步驟由一個方法表示
	public void templateMethod() {
		hookMethod();
		primitiveoperationA();
		primitiveoperationB();

	}

	// 鉤子方法,鉤子可以讓子類實現算法中可選部分
	public void hookMethod() {
		System.out.println("鉤子方法,空(或默認)實現,子類重寫實現相應的邏輯。");
	}

	// 抽象方法,由子類實現
	public abstract void primitiveoperationA();

	public abstract void primitiveoperationB();

}

// 具體類
public class ConcreteClass extends AbstractClass {

	@Override
	public void primitiveoperationA() {
		System.out.println("primitiveoperationA() 被調用。。。");
	}

	@Override
	public void primitiveoperationB() {
		System.out.println("primitiveoperationA() 被調用。。。");
	}

}

// 測試客戶端
public class TestClient {

	public static void main(String[] args) {
		
		AbstractClass concrete = new ConcreteClass();
		concrete.templateMethod();
	}

}

從代碼實現可以看出:父類(高層組件)控制何時以及如何讓(子類方法)低層組件參與,也就是說,高層組件對低層組件的方式是“別調用我,我會調用你們”,完美的體現了好萊塢原則。

已知應用

  • java.util.Collections#sort()
  • java.io.InputStream#read()

相關模式

模板方法、策略模式

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章