【設計模式(22)】行為型模式之模板模式
個人學習筆記分享,當前能力有限,請勿貶低,菜鳥互學,大佬繞道
如有勘誤,歡迎指出和討論,本文後期也會進行修正和補充
開發過程中,我們通常會遇到這樣的情況:我們已經制定好了方案,並確定了相關執行步驟,但某些具體的步驟還未知,或者說具體的步驟與環境相關
如,乘坐飛機、火車等交通工具出遠門,都需要買票-驗票進站-等車-上車-下車-出站等一套流程,但具體需要處理的細節卻不完全一樣,買票的渠道、驗票進站的步驟、上下飛機/火車的方式等等,都不一樣。
那麼,我們可以把這些規定了流程或格式的例項定義成模板,允許使用者根據自己的需求去更新它
1.定義
使用目的:定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟
使用時機:有一套相同的流程,但具體實現方案不一樣
解決問題:流程中的一些方法通用,卻在每一個子類都重新寫了這一方法。
實現方法:流程在抽象類實現,步驟在子類實現。
應用例項:
- 乘坐飛機、火車、輪船等交通工具的流程,都需要買票-驗票-候車-上車-下車-出站的流程
- spring對事務的處理,如開啟事務、獲取 Session、關閉 Session 等
- MVC模型
優點:
- 封裝不變部分,擴充套件可變部分。
- 提取公共程式碼,便於維護。
- 行為由父類控制,子類實現
缺點:
- 對每個不同的實現都需要定義一個子類,這會導致類的個數增加,系統更加龐大,設計也更加抽象,間接地增加了系統實現的複雜度。
- 父類中的抽象方法由子類實現,子類執行的結果會影響父類的結果,這導致一種反向的控制結構,它提高了程式碼閱讀的難度。
- 由於繼承關係自身的缺點,如果父類新增新的抽象方法,則所有子類都要改一遍。
注意事項:為防止惡意操作,一般模板方法都加上 final 關鍵詞。
2.結構
模板模式包含以下角色:
- 抽象類/抽象模板(Abstract Class):負責給出一個演算法的輪廓和骨架。它由一個模板方法和若干個基本方法構成
- 具體子類/具體實現(Concrete Class):實現抽象類中所定義的抽象方法和鉤子方法,它們是一個頂級邏輯的一個組成步驟
3.步驟
-
構建抽象模板類
//抽象類 abstract class AbstractClass { //模板方法 public void TemplateMethod() { SpecificMethod(); abstractMethod1(); abstractMethod2(); abstractMethod3(); } //具體方法 public void SpecificMethod() { System.out.println("抽象類中的具體方法被呼叫..."); } //抽象方法1 public abstract void abstractMethod1(); //抽象方法2 public abstract void abstractMethod2(); //抽象方法2 public abstract void abstractMethod3(); }
-
構建具體子類
//具體子類A class ConcreteClassA extends AbstractClass { public void abstractMethod1() { System.out.println("模板A中的方法1被呼叫"); } public void abstractMethod2() { System.out.println("模板A中的方法2被呼叫..."); } @Override public void abstractMethod3() { System.out.println("模板A中的方法3被呼叫..."); } } //具體子類B class ConcreteClassB extends AbstractClass { public void abstractMethod1() { System.out.println("模板B中的方法1被呼叫"); } public void abstractMethod2() { System.out.println("模板B中的方法2被呼叫..."); } @Override public void abstractMethod3() { System.out.println("模板B中的方法3被呼叫..."); } }
測試程式碼
public class TemplateTest {
public static void main(String[] args) {
AbstractClass tmA = new ConcreteClassA();
tmA.TemplateMethod();
AbstractClass tmB = new ConcreteClassB();
tmB.TemplateMethod();
}
}
執行結果
4.擴充套件
模板模式由抽象模板規定了演算法的骨架,即具體方法的執行順序和邏輯
那麼,我們可以通過鉤子方法,使不同的具體子類能夠執行不同的具體方法
具體程式碼
package com.company.designPattern.template;
public class TemplateHockTest {
public static void main(String[] args) {
AbstractHockClass tmA = new ConcreteHockClassA();
tmA.TemplateMethod();
}
}
//抽象類
abstract class AbstractHockClass {
//模板方法
public void TemplateMethod() {
SpecificMethod();
// 執行鉤子1和具體方法1
hockMethod1();
abstractMethod1();
// 根據鉤子2結果是否執行具體方法2
if (hockMethod2()) {
abstractMethod2();
}
}
//具體方法
public void SpecificMethod() {
System.out.println("抽象類中的具體方法被呼叫...");
}
// 鉤子方法1
public void hockMethod1() {
System.out.println("預設鉤子方法1被呼叫");
}
//抽象方法1
public abstract void abstractMethod1();
// 鉤子方法2
public boolean hockMethod2() {
System.out.println("預設鉤子方法2被呼叫");
return true;
}
//抽象方法2
public abstract void abstractMethod2();
}
//具體子類A
class ConcreteHockClassA extends AbstractHockClass {
public void abstractMethod1() {
System.out.println("模板A中的方法1被呼叫");
}
public void abstractMethod2() {
System.out.println("模板A中的方法2被呼叫...");
}
@Override
public boolean hockMethod2() {
System.out.println("預設鉤子方法2被呼叫");
return false;
}
}
通過鉤子方法,我們達到下面效果
- 執行通用具體方法
- 通過鉤子1對方法1進行預處理
- 根據鉤子2判斷是否執行方法2
執行結果
後記
模板方法的目的是將按照統一模板的方法進一步規範化,通過繼承重寫和模板方法來保證多個具體子類按照同樣的演算法執行
說白點,量產化,將統一的方法通過父類的abstract方法控制,統一的流程通過父類中的模板方法設定,子類自行控制每個步驟的執行細節
當然也可以根據實際需求進行變型,畢竟服務於實際開發才是設計模式的目的
作者:Echo_Ye
WX:Echo_YeZ
Email :[email protected]
個人站點:在搭了在搭了。。。(右鍵 - 新建資料夾)