模板模式
簡介:
設計一個系統時知道了算法所需的關鍵步驟,而且確定了這些步驟的執行順序,但某些步驟的具體實現還未知,或者說某些步驟的實現與具體的環境相關。
例如,去銀行辦理業務一般要經過以下4個流程:取號、排隊、辦理具體業務、對銀行工作人員進行評分等,其中取號、排隊和對銀行工作人員進行評分的業務對每個客戶是一樣的,可以在父類中實現,但是辦理具體業務卻因人而異,它可能是存款、取款或者轉賬等,可以延遲到子類中實現。
定義:
- 模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern),
在一個抽象類公開定義了執行它的方法的模板。它的子類可以按需要重寫方法
實現,但調用將以抽象類中定義的方式進行。 - 簡單說,模板方法模式 定義一個操作中的算法的骨架,而將一些步驟延遲到子
類中,使得子類可以不改變一個算法的結構,就可以重定義該算法的某些特定
步驟 - 這種類型的設計模式屬於行爲型模式。
模式的結構:
模板方法模式包含以下主要角色。
(1) 抽象類(Abstract Class):負責給出一個算法的輪廓和骨架。它由一個模板方法和若干個基本方法構成。這些方法的定義如下。
① 模板方法:定義了算法的骨架,按某種順序調用其包含的基本方法。
② 基本方法:是整個算法中的一個步驟,包含以下幾種類型。
抽象方法:在抽象類中申明,由具體子類實現。
具體方法:在抽象類中已經實現,在具體子類中可以繼承或重寫它。
鉤子方法:在抽象類中已經實現,包括用於判斷的邏輯方法和需要子類重寫的空方法兩種。鉤子就是給子類一個授權,讓子類來決定模板方法的邏輯執行。就比如在炒西紅柿雞蛋的時候,由子類去決定是否要加調料。我們去實現一下
(2) 具體子類(Concrete Class):實現抽象類中所定義的抽象方法和鉤子方法,它們是一個頂級邏輯的一個組成步驟。
抽象類:
/**
* @author 孫一鳴 on 2020/2/14
* 抽象模板結構
*/
public abstract class AbstractClass {
//模板方法 用來控制子類的順序 要想有人生必須按老爸的人生順序來
//聲明final不讓子類覆蓋這個方法,防止改變人生順序
public final void 人生() {
學習();
工作();
if (hasLove()) {
愛情();
}
}
//家裏窮更得用工學習
public void 學習() {
System.out.println("每天晚上趴在鄰居窗上學習");
}
//工作必須穩定
public void 工作() {
System.out.println("從一而終");
}
//戀愛自由 讓兒子自由戀去,隨意找對象
public abstract void 愛情();
//假如我們想要有一個兒子,不想結婚,但是抽象方法必須要實現
//這個時候我們需要 -- 鉤子方法
//提供一個默認或者空的實現
boolean hasLove() {
return true;
}
}
具體子類A:
/**
* 好兒子 按照父親定義的抽象模板類 走完人生
*
* @author 孫一鳴 on 2020/2/14
*/
public class ConcreteClassA extends AbstractClass{
@Override
public void 學習() {
//兒子不認可父親的學習方法 考高分影響同學關係
System.out.println("高考狀元。。");
}
//父親給我愛情自由 一定好好談戀愛
@Override
public void 愛情() {
System.out.println("膚白貌美大長腿...");
}
}
具體子類B:
/**
* 壞兒子 也按照父親定義的抽象模板類 走完人生
*
* @author 孫一鳴 on 2020/2/14
*/
public class ConcreteClassB extends AbstractClass {
@Override
public void 學習() {
//學習無用
System.out.println("0分萬歲...");
}
//隨意結合
@Override
public void 愛情() {
System.out.println("矮窮矬...");
}
}
具體子類C:
/**
* 不想結婚的兒子 也按照父親定義的抽象模板類 走完人生
*
* @author 孫一鳴 on 2020/2/14
*/
public class ConcreteClassC extends AbstractClass {
@Override
public void 學習() {
//學習無用
System.out.println("60分萬歲...");
}
//隨意結合
@Override
public void 愛情() {
//因爲不想要結婚 所以空實現
}
//子類通過覆蓋的方式去掛載鉤子函數
@Override
boolean hasLove() {
return false;
}
}
模板方法模式的注意事項和細節
- 基本思想是:算法只存在於一個地方,也就是在父類中,容易修改。需要修改算
法時,只要修改父類的模板方法或者已經實現的某些步驟,子類就會繼承這些修改 - 實現了最大化代碼複用。父類的模板方法和已實現的某些步驟會被子類繼承而直接
使用。 - 既統一了算法,也提供了很大的靈活性。父類的模板方法確保了算法的結構保持不變,同時由子類提供部分步驟的實現。
- 該模式的不足之處:每一個不同的實現都需要一個子類實現,導致類的個數增加,
使得系統更加龐大 - 一般模板方法都加上final關鍵字, 防止子類重寫模板方法.
- 模板方法模式使用場景:當要完成在某個過程,該過程要執行一系列步驟 ,這一
系列的步驟基本相同,但其個別步驟在實現時 可能不同,通常考慮用模板方法模
式來處理