設計模式——模版方法設計模式(行為型)

摘要

模版方法設計模式是一種行為型設計模式,定義了算法的步驟順序和整體結構,將某些步驟的具體實現延遲到子類中。它通過抽象類定義模板方法,子類實現抽象步驟,實現代碼復用和算法流程控制。該模式適用于有固定流程但部分步驟可變的場景,如業務流程控制等。

1. 模版設計模式定義

定義一個操作中的算法骨架(即步驟的順序和整體結構),而將某些步驟的具體實現延遲到子類中。子類可以在不改變算法結構的前提下,重新定義算法中的某些具體步驟。

1.1.1. 模版設計模式的關鍵點

  • 抽象模版類:定義一個模板方法,描述算法的整體流程。模板方法一般是 final,防止子類改變算法結構。
  • 基本方法(基本操作):模板方法所依賴的步驟,這些步驟可以是抽象的,也可以有默認實現。
  • 具體子類:實現抽象類中的抽象步驟,完成具體的業務邏輯。

1.1.2. 作用

  • 復用代碼:把不變的行為放在父類,變化的行為由子類實現,避免代碼重復。
  • 控制算法流程:子類只需關注具體步驟實現,算法整體流程由父類控制,增強代碼的可維護性和可擴展性。

2. 模版設計模式結構

  1. 抽象類 (Abstract-Class) 會聲明作為算法步驟的方法, 以及依次調用它們的實際模板方法。 算法步驟可以被聲明為 抽象類型, 也可以提供一些默認實現。
  2. 具體類 (Concrete-Class) 可以重寫所有步驟, 但不能重寫模板方法自身。

2.1. 模版設計模式類圖

2.2. 模版設計模式時序圖

3. 模版設計模式實現方式

3.1. 模版設計模式的實現方式核心在于:

  • 在抽象父類中定義一個模板方法(通常是final的),它規定了算法的執行順序和骨架。
  • 模板方法調用若干個基本方法(步驟),其中部分基本方法是抽象的,由子類實現;部分基本方法可以有默認實現。
  • 子類繼承抽象父類,實現抽象步驟,完成具體業務邏輯。

3.2. 模板設計模式實現步驟

  1. 創建抽象類(AbstractClass)
    • 定義模板方法templateMethod(),并用final修飾,防止子類重寫改變流程。
    • 模板方法中按照固定步驟順序調用基本操作。
    • 定義基本操作(抽象方法或具體方法),其中抽象方法由子類實現。
  1. 創建具體子類(ConcreteClass)
    • 繼承抽象類,實現抽象的基本方法,完成具體業務。

3.3. 示例代碼(Java)

// 抽象模板類
public abstract class AbstractTemplate {// 模板方法,定義固定流程,防止子類覆蓋public final void templateMethod() {step1();step2();step3();}// 抽象基本操作,由子類實現protected abstract void step1();protected abstract void step2();// 具體基本操作,父類實現,子類可選擇復寫protected void step3() {System.out.println("默認實現步驟3");}
}// 具體子類A
public class ConcreteTemplateA extends AbstractTemplate {@Overrideprotected void step1() {System.out.println("ConcreteTemplateA 實現步驟1");}@Overrideprotected void step2() {System.out.println("ConcreteTemplateA 實現步驟2");}
}// 具體子類B
public class ConcreteTemplateB extends AbstractTemplate {@Overrideprotected void step1() {System.out.println("ConcreteTemplateB 實現步驟1");}@Overrideprotected void step2() {System.out.println("ConcreteTemplateB 實現步驟2");}// 可以覆蓋父類默認實現@Overrideprotected void step3() {System.out.println("ConcreteTemplateB 重寫步驟3");}
}

3.4. 模版模式示例

public class Client {public static void main(String[] args) {AbstractTemplate templateA = new ConcreteTemplateA();templateA.templateMethod();// 輸出:// ConcreteTemplateA 實現步驟1// ConcreteTemplateA 實現步驟2// 默認實現步驟3AbstractTemplate templateB = new ConcreteTemplateB();templateB.templateMethod();// 輸出:// ConcreteTemplateB 實現步驟1// ConcreteTemplateB 實現步驟2// ConcreteTemplateB 重寫步驟3}
}

說明

  • 模板方法templateMethod()固定了整體流程,子類不能改變流程,只能重寫步驟細節。
  • 這樣保證了算法骨架不變,細節可變。

4. 模版設計模式適合場景

4.1. ? 適合使用模版設計模式的場景

場景

說明

多個子類有相同算法骨架

多個子類共享固定流程,只有具體步驟實現不同,便于代碼復用和規范流程。

需要復用公共流程代碼

將不變的算法結構封裝在父類,避免重復代碼,提升維護性。

需要統一控制算法執行順序

模板方法定義執行順序,防止子類隨意改變流程,保證算法正確執行。

算法結構清晰、變化點集中

業務流程穩定,只有個別步驟需要子類實現,方便集中管理和擴展。

希望固定流程,允許步驟擴展

允許子類通過實現抽象步驟或覆蓋鉤子方法靈活擴展功能,而不破壞整體流程。

4.2. ? 不適合使用模版設計模式的場景

場景

原因

需要動態調整或拼裝流程

模板方法流程固定,難以支持運行時動態改變步驟或流程組合。

繼承層次過深,代碼復雜

模板方法依賴繼承,過多層次會導致系統復雜且難維護。

業務變化點不明顯或過少

過度抽象導致代碼冗余,簡單業務用模版模式反而增加復雜度。

多維度變化且復雜

多個變化點分布在算法不同部分,模板方法難以靈活應對,策略模式或責任鏈模式更合適。

需要高度靈活、組合式的行為

模板方法結構靜態,不適合高動態組合或插件式設計。

5. 模版設計模式實戰示例

5.1. 場景描述

在金融風控中,不同風控策略的執行流程大致相同:

  1. 數據準備
  2. 規則校驗
  3. 風控決策(通過/拒絕)
  4. 結果記錄

不同風控策略的規則校驗細節不同,適合用模板設計模式抽象固定流程,把校驗邏輯由子類實現。

5.2. 項目結構示例(Spring Boot)

com.example.riskcontrol
├── RiskControlTemplate.java      // 抽象模板類
├── UserRiskControl.java          // 具體風控策略1
├── TransactionRiskControl.java   // 具體風控策略2
├── RiskControlService.java       // 調用客戶端
└── SpringBootApplication.java    // 啟動類

5.3. 抽象模板類 RiskControlTemplate

package com.example.riskcontrol;public abstract class RiskControlTemplate {// 模板方法,定義風控流程public final void executeRiskControl(String userId) {prepareData(userId);boolean passed = validateRules(userId);makeDecision(passed);recordResult(userId, passed);}// 準備數據,具體實現可重寫,默認空實現protected void prepareData(String userId) {System.out.println("準備風控數據,用戶ID:" + userId);}// 抽象規則校驗步驟,由具體策略實現protected abstract boolean validateRules(String userId);// 風控決策步驟,固定流程private void makeDecision(boolean passed) {if (passed) {System.out.println("風控通過,繼續后續流程");} else {System.out.println("風控拒絕,終止流程");}}// 記錄風控結果,默認實現protected void recordResult(String userId, boolean passed) {System.out.println("記錄風控結果,用戶ID:" + userId + ", 結果:" + (passed ? "通過" : "拒絕"));}
}

5.4. 具體策略實現類

package com.example.riskcontrol;import org.springframework.stereotype.Component;@Component("userRiskControl")
public class UserRiskControl extends RiskControlTemplate {@Overrideprotected boolean validateRules(String userId) {System.out.println("執行用戶維度的風控規則校驗,用戶ID:" + userId);// 簡單示例,實際接入數據庫或外部接口判斷return userId.hashCode() % 2 == 0;  // 偶數通過,奇數拒絕}
}
package com.example.riskcontrol;import org.springframework.stereotype.Component;@Component("transactionRiskControl")
public class TransactionRiskControl extends RiskControlTemplate {@Overrideprotected boolean validateRules(String userId) {System.out.println("執行交易維度的風控規則校驗,用戶ID:" + userId);// 這里模擬判斷交易風險return userId.length() > 5;  // 用戶ID長度大于5通過}
}

5.5. 業務調用層 RiskControlService

package com.example.riskcontrol;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Map;@Service
public class RiskControlService {// 用Spring注解注入所有實現的模板,key為bean名字private final Map<String, RiskControlTemplate> riskControlMap;@Autowiredpublic RiskControlService(Map<String, RiskControlTemplate> riskControlMap) {this.riskControlMap = riskControlMap;}// 執行指定策略public void executeRiskControl(String strategyName, String userId) {RiskControlTemplate strategy = riskControlMap.get(strategyName);if (strategy == null) {throw new IllegalArgumentException("未找到對應風控策略:" + strategyName);}strategy.executeRiskControl(userId);}
}

5.6. Spring Boot 啟動類

package com.example.riskcontrol;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringBootRiskControlApplication implements CommandLineRunner {@Autowiredprivate RiskControlService riskControlService;public static void main(String[] args) {SpringApplication.run(SpringBootRiskControlApplication.class, args);}@Overridepublic void run(String... args) throws Exception {System.out.println("模擬執行用戶風控策略:");riskControlService.executeRiskControl("userRiskControl", "user12345");System.out.println("\n模擬執行交易風控策略:");riskControlService.executeRiskControl("transactionRiskControl", "user12345");}
}

5.7. 運行結果示例

模擬執行用戶風控策略:
準備風控數據,用戶ID:user12345
執行用戶維度的風控規則校驗,用戶ID:user12345
風控拒絕,終止流程
記錄風控結果,用戶ID:user12345, 結果:拒絕模擬執行交易風控策略:
準備風控數據,用戶ID:user12345
執行交易維度的風控規則校驗,用戶ID:user12345
風控通過,繼續后續流程
記錄風控結果,用戶ID:user12345, 結果:通過

5.8. 模版模式總結

  • 抽象父類 RiskControlTemplate 封裝公共流程(模板方法)。
  • 具體策略類只需實現風控規則校驗步驟。
  • 通過 Spring 的 @Component 注解和自動裝配 Map<String, RiskControlTemplate>,方便策略的靈活管理和調用。

6. 模版設計模式思考

6.1. 模版設計模式是不是用于父子類?

是的,模板設計模式(Template Method Pattern)確實是基于父子類繼承關系實現的設計模式

6.1.1. 關鍵點總結:

  • 父類(抽象類):定義一個模板方法,規定算法的整體流程和執行順序。模板方法通常是 final,防止子類改變流程。
  • 子類(具體類):繼承父類,實現父類中定義的抽象步驟,完成具體業務邏輯。

換句話說,模板模式就是把不變的流程寫在父類里,把可變的步驟留給子類實現。

6.1.2. 為什么是父子類?

  • 模板方法模式的核心就是“復用公共代碼,且允許子類重寫部分行為”,這是繼承的典型應用場景。
  • 父類定義了算法框架,子類只實現細節,滿足“開閉原則”(對擴展開放,對修改關閉)。

6.1.3. 舉個簡單類比:

  • 父類像“烘焙蛋糕的流程”
  • 子類像“不同口味蛋糕的具體做法”(巧克力、草莓等)

父類確定做蛋糕的步驟(比如準備材料、攪拌、烘焙、裝飾),子類決定每步的具體實現。

模板設計模式在實戰開發中常和以下設計模式配合使用,發揮協同優勢:

6.2. 模版設計模式常和哪些模式用于實戰開發中?

設計模式

結合方式及應用場景

策略模式

模板模式定義算法骨架,策略模式封裝可替換的具體行為,實現靈活的步驟替換。比如模板方法中調用策略接口完成某步驟。

工廠方法模式

用工廠方法創建模板方法中需要的具體實現對象,解耦模板和具體子類的實例化。

鉤子方法(Hook Method)

模板方法模式中提供可選的“鉤子”方法,允許子類決定是否覆蓋,靈活控制流程細節。

裝飾器模式

在模板方法執行前后動態增強功能,如日志、權限校驗等,避免修改模板代碼。

責任鏈模式

將模板方法中的步驟拆分成責任鏈上的多個處理對象,形成更靈活的處理流程。

命令模式

模板方法中調用命令對象完成某些具體操作,命令模式封裝請求,增強擴展性。

觀察者模式

模板方法執行過程中發生重要事件時通知觀察者,實現業務解耦。

簡單示例場景

  • 金融風控:模板定義風控流程,策略模式封裝不同風控規則。
  • Web請求處理:模板方法定義請求處理流程,工廠方法創建具體處理器。
  • 消息發送:模板定義消息發送步驟,裝飾器動態添加日志或限流。

博文參考

  • 模板方法設計模式
  • 設計模式之模板方法模式 | DESIGN

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/83285.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/83285.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/83285.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python使用

Python學習&#xff0c;從安裝&#xff0c;到簡單應用 前言 Python作為膠水語言在web開發&#xff0c;數據分析&#xff0c;網絡爬蟲等方向有著廣泛的應用 一、Python入門 相關基礎語法直接使用相關測試代碼 Python編譯器版本使用3以后&#xff0c;安裝參考其他教程&#xf…

吳恩達機器學習筆記(1)—引言

目錄 一、歡迎 二、機器學習是什么 三、監督學習 四、無監督學習 一、歡迎 機器學習是當前信息技術領域中最令人興奮的方向之一。在這門課程中&#xff0c;你不僅會學習機器學習的前沿知識&#xff0c;還將親手實現相關算法&#xff0c;從而深入理解其內部機理。 事實上&…

java筆記08

多線程&JUC 1.什么是多線程 1.什么是多線程&#xff1f;有了多線程&#xff0c;我們就可以讓程序同時做多件事情 2.多線程的作用&#xff1f;提高效率 3.多線程的應用場景&#xff1f;只要你想讓多個事情同時運行就需要用到多線程比如&#xff1a;軟件中的耗時操作、所有…

【仿muduo庫實現并發服務器】使用正則表達式提取HTTP元素

使用正則表達式提取HTTP元素 1.正則表達式2.正則庫的使用3.使用正則表達式提取HTTP請求行 1.正則表達式 正則表達式它其實是描述了一種字符串匹配的模式&#xff0c;它可以用來在一個字符串中檢測一個特定格式的字串&#xff0c;以及可以將符合特定規則的字串進行替換或者提取…

顯示即戰略:鐵電液晶如何成為 “數字中國” 的 “像素基石”?

一、顯示技術&#xff1a;數字時代的核心戰略支點 &#xff08;一&#xff09;從 “視覺窗口” 到 “戰略基礎設施” 在數字經濟蓬勃發展的當下&#xff0c;顯示技術早已超越了單純的 “視覺呈現” 范疇&#xff0c;成為連接人與數字世界的關鍵接口。從智能手機、平板電腦到車…

適合小白的超詳細配置YOLOv8教程(畢設必看)(訓練自己數據集)(Pycharm保姆級安裝教程)(lablme的使用)(GPU版)

目錄 1.Pycharm的安裝和虛擬環境調用&#xff08;已經安裝好的可以跳過此步驟&#xff09; 1.1 下載pycharm軟件 1.2 調用已創建虛擬環境&#xff08;調用上一篇教程中創建好的虛擬環境&#xff09; 2.標注自己數據集&#xff08;已有數據集的這部分可跳過&#xff09; 2.1…

EC800X QuecDuino開發板介紹

支持的模組列表 EG800KEC800MEC800GEC800E 功能列表 基本概述 EC800X QuecDuino EVB 搭載移遠 EC800 系列模組。支持模組型號為&#xff1a; EC800M 系列、EC800K 系列、EG800K 系列、EC800E 系列等。 渲染圖 開發板的主要組件、接口布局見下圖 資料下載 EC800X-QuecDui…

Unity + HybirdCLR熱更新 入門篇

官方文檔 HybridCLR | HybridCLRhttps://hybridclr.doc.code-philosophy.com/docs/intro 什么是HybirdCLR? HybridCLR&#xff08;原名 huatuo&#xff09;是一個專為 Unity 項目設計的C#熱更新解決方案&#xff0c;它通過擴展 IL2CPP 運行時&#xff0c;使其支持動態加載和…

類 Excel 數據填報

類 Excel 填報模式&#xff0c;滿足用戶 Excel 使用習慣 數據填報&#xff0c;可作為獨立的功能模塊&#xff0c;用于管理業務流程、匯總采集數據&#xff0c;以及開發各類數據報送系統&#xff0c;因此&#xff0c;對于報表工具而言&#xff0c;其典型場景之一就是利用報表模…

MySQL 8.0 OCP 英文題庫解析(十)

Oracle 為慶祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免費考取原價245美元的MySQL OCP 認證。 從今天開始&#xff0c;將英文題庫免費公布出來&#xff0c;并進行解析&#xff0c;幫助大家在一個月之內輕松通過OCP認證。 本期公布試題81~90 試題81:…

JavaScript 性能優化實戰:從原理到框架的全棧優化指南

在 Web 應用復雜度指數級增長的今天&#xff0c;JavaScript 性能優化已成為衡量前端工程質量的核心指標。本文將結合現代瀏覽器引擎特性與一線大廠實踐經驗&#xff0c;構建從基礎原理到框架定制的完整優化體系&#xff0c;助你打造高性能 Web 應用。 一、性能優化基礎&#x…

基于Web的分布式圖集管理系統架構設計與實踐

引言&#xff1a;為什么需要分布式圖集管理&#xff1f; 在現代Web圖形應用中&#xff0c;紋理圖集&#xff08;Texture Atlas&#xff09;技術是優化渲染性能的關鍵手段。傳統的圖集制作流程通常需要美術人員使用專業工具&#xff08;如TexturePacker&#xff09;離線制作&am…

鴻蒙OS在UniApp中集成Three.js:打造跨平臺3D可視化應用#三方框架 #Uniapp

在UniApp中集成Three.js&#xff1a;打造跨平臺3D可視化應用 引言 在最近的一個項目中&#xff0c;我們需要在UniApp應用中展示3D模型&#xff0c;并實現實時交互功能。經過技術選型和實踐&#xff0c;我們選擇了Three.js作為3D渲染引擎。本文將分享我們在UniApp中集成Three.…

Flask中關于app.url_map屬性的用法

目錄 一、app.url_map 是什么? 二、可以查看哪些信息? 三、示例:打印所有路由 四、結合 url_for() 使用 五、常見用途場景 六、結合 Flask CLI 使用 總結 app.url_map 是 Flask 中非常重要的一個屬性,用于查看或操作整個應用的 URL 路由映射表(routing map)。它展…

SpringBoot項目搭建指南

SpringBoot項目搭建指南 文章目錄 SpringBoot項目搭建指南一、SpringBoot項目搭建1.1 SpringBoot 版本選擇1.2 SpringBoot 框架引入方式1.2.1 繼承 Starter Parent POM1.2.2 不使用 Parent POM 來使用 Spring Boot 1.3 SpringBoot 打包插件 二、日志框架引入2.1 引入SpringBoot…

數據庫系統概論(十六)數據庫安全性(安全標準,控制,視圖機制,審計與數據加密)

數據庫系統概論&#xff08;十六&#xff09;數據庫安全性 前言一、數據庫安全性1. 什么是數據庫安全性&#xff1f;2. 為何會存在安全問題&#xff1f; 二、安全標準的發展1. 早期的“開拓者”&#xff1a;TCSEC標準2. 走向國際統一&#xff1a;CC標準3. TCSEC和CC標準有什么不…

Jvm 元空間大小分配原則

JVM元空間&#xff08;Metaspace&#xff09;的大小分配原則與系統物理內存密切相關&#xff0c;但并不是直接等比例分配&#xff0c;而是通過一系列參數和JVM的動態管理機制來確定。下面從原理和實際行為兩方面詳細說明&#xff1a; 1. 元空間&#xff08;Metaspace&#xff0…

編程之巔:語言的較量

第一章&#xff1a;代碼之城的召集令 在遙遠的數字大陸上&#xff0c;有一座名為“代碼之城”的神秘都市。這里居住著各種編程語言的化身&#xff0c;他們以擬人化的形態生活&#xff0c;每種語言都有獨特的性格與技能。Python是個優雅的學者&#xff0c;C是個硬核戰士&#x…

飛牛fnNAS裝機之迷你小主機的利舊

前幾天找Console線的時候,翻出一臺迷你小主機,想起來以前是做“軟路由”用的,現在用不上了。本想放回箱子,但突然想起最近正在做飛牛NAS的專題,不如將其改造成NAS得了。 這個東東有HDMI、VGA接口,2個USB(其中一個支持3.0),還有4個網口。 打開機蓋,看看內部情況。發現…

uv:一個現代化的 Python 依賴管理工具

在 Python 的生態系統中&#xff0c;依賴管理和 Python 版本管理一直是開發者關注的核心問題。傳統的工具如 pip、poetry 和 pyenv 雖然功能強大&#xff0c;但在性能和使用體驗上仍有改進空間。uv 是由 Python 核心開發者開發的 現代化依賴管理工具&#xff0c;旨在提供更快、…