設計模式精講 Day 22:模板方法模式(Template Method Pattern)

【設計模式精講 Day 22】模板方法模式(Template Method Pattern)


文章標簽

設計模式, 模板方法模式, Java開發, 面向對象設計, 軟件架構, 設計模式實戰, Java應用開發


文章簡述

模板方法模式是一種行為型設計模式,它通過定義一個算法的骨架,并將某些步驟延遲到子類中實現。這種模式允許子類在不改變算法結構的前提下,重新定義算法的某些步驟,從而提高代碼復用性和可擴展性。本文作為“設計模式精講”系列的第22天,深入講解了模板方法模式的核心思想、實現方式和實際應用場景。文章通過完整的Java代碼示例,展示了如何在具體業務場景中使用模板方法模式優化系統結構,并結合真實案例分析其優勢與局限性。無論你是初學者還是有經驗的開發者,這篇文章都將幫助你掌握模板方法模式的設計精髓并應用于實際項目中。


【設計模式精講 Day 22】模板方法模式(Template Method Pattern)

開篇:模板方法模式的核心思想與應用價值

今天是“設計模式精講”系列的第22天,我們聚焦于模板方法模式(Template Method Pattern)。模板方法模式是一種行為型設計模式,它通過定義一個算法的骨架,并將某些步驟延遲到子類中實現,使得子類可以在不改變算法結構的前提下,重新定義算法的某些步驟。

在軟件開發中,很多業務流程具有固定的執行順序,但其中某些步驟可能因具體需求而變化。例如,支付流程通常包括驗證、扣款、記錄日志等步驟,但不同支付方式的具體實現可能不同。如果直接在同一個類中處理這些邏輯,會導致代碼重復和難以維護。而模板方法模式通過將公共邏輯封裝在父類中,將可變部分交給子類實現,實現了算法結構與具體實現的解耦。

本篇文章將從模式定義、結構、適用場景、實現方式、工作原理、優缺點分析、案例分析等多個維度,全面解析模板方法模式,并提供完整可運行的Java代碼示例,幫助你真正掌握這一設計模式。


模式定義

1.1 正式定義

模板方法模式(Template Method Pattern)是一種行為型設計模式,它定義了一個算法的框架,并在該框架中調用一些抽象方法或鉤子方法,由子類來實現這些方法。這樣,算法的結構保持不變,但具體的實現可以由不同的子類進行定制。

1.2 核心思想

  • 算法骨架固定:算法的整體流程由父類定義。
  • 具體步驟延遲實現:部分步驟由子類實現,增強靈活性。
  • 復用性高:避免重復代碼,提升代碼復用性。
  • 符合開閉原則:對擴展開放,對修改關閉。

模式結構

2.1 UML 類圖說明(文字描述)

模板方法模式包含以下幾個關鍵角色:

角色說明
AbstractClass(抽象類)定義算法的骨架,包含模板方法和抽象方法。
ConcreteClass(具體類)實現抽象方法,完成算法的具體步驟。

2.2 示例結構說明

  • AbstractClass 中定義了一個 templateMethod() 方法,該方法調用了多個抽象方法(如 primitiveOperation1()primitiveOperation2() 等)。
  • ConcreteClassAConcreteClassB 分別實現這些抽象方法,提供不同的具體邏輯。

適用場景

場景說明
多個類有相似的算法流程當多個類需要按照相同流程執行操作時,適合使用模板方法模式。
算法的某些步驟可能變化如果算法中的某些步驟需要根據情況變化,適合將其封裝為抽象方法。
提高代碼復用性將公共邏輯放在父類中,減少重復代碼。
控制算法的執行順序保證算法的執行順序一致,同時允許子類自定義部分步驟。

實現方式

3.1 Java 代碼實現

以下是一個基于模板方法模式的簡單示例,模擬一個“咖啡與茶的制作流程”。

3.1.1 抽象類
// Beverage.java
public abstract class Beverage {// 模板方法:定義算法的骨架public final void prepareRecipe() {boilWater();brew();pourInCup();addCondiments();}// 具體方法:所有子類共有的步驟private void boilWater() {System.out.println("煮水");}private void pourInCup() {System.out.println("倒入杯子");}// 抽象方法:子類需要實現的方法protected abstract void brew();// 鉤子方法:可選實現protected boolean isCondimentRequired() {return true;}// 子類可以選擇是否重寫此方法protected void addCondiments() {if (isCondimentRequired()) {System.out.println("添加配料");}}
}
3.1.2 具體類
// Coffee.java
public class Coffee extends Beverage {@Overrideprotected void brew() {System.out.println("沖泡咖啡");}@Overrideprotected boolean isCondimentRequired() {return true; // 咖啡需要加糖}
}// Tea.java
public class Tea extends Beverage {@Overrideprotected void brew() {System.out.println("沖泡茶葉");}@Overrideprotected boolean isCondimentRequired() {return false; // 茶不需要加糖}
}
3.1.3 測試類
// TemplateMethodPatternTest.java
public class TemplateMethodPatternTest {public static void main(String[] args) {Beverage coffee = new Coffee();coffee.prepareRecipe();System.out.println("-----------");Beverage tea = new Tea();tea.prepareRecipe();}
}

輸出:

煮水
沖泡咖啡
倒入杯子
添加配料
-----------
煮水
沖泡茶葉
倒入杯子

工作原理

模板方法模式通過將算法的通用邏輯封裝在父類中,而將特定邏輯交由子類實現,從而實現算法結構與具體實現的分離。

  • 模板方法:定義算法的步驟,調用抽象方法或鉤子方法。
  • 抽象方法:由子類實現,提供具體邏輯。
  • 鉤子方法:提供默認實現,子類可以選擇是否覆蓋。

這種機制符合開閉原則,即對擴展開放,對修改關閉。同時,也符合單一職責原則,每個類只關注自己的職責。


優缺點分析

優點缺點
代碼復用性強:公共邏輯集中管理,避免重復代碼。增加類的數量:每個子類都需要繼承抽象類。
提高可維護性:算法結構清晰,便于后期維護和擴展。靈活性有限:如果算法結構頻繁變化,可能需要重構。
符合開閉原則:新增功能只需擴展子類,無需修改現有代碼。過度依賴繼承:可能導致類層次復雜。

案例分析:電商訂單處理流程中的模板方法模式應用

4.1 問題描述

某電商平臺的訂單處理流程包括:校驗訂單、計算價格、生成發票、發送通知等步驟。不同類型的訂單(如普通訂單、促銷訂單、預售訂單)在某些步驟上存在差異,如促銷訂單需要額外的折扣計算,預售訂單需要庫存預扣。

4.2 解決方案

采用模板方法模式重構訂單處理流程,將通用邏輯放在父類中,將可變部分交給子類實現。

4.2.1 抽象類
// OrderProcessor.java
public abstract class OrderProcessor {// 模板方法public final void processOrder(Order order) {validate(order);calculatePrice(order);generateInvoice(order);sendNotification(order);}protected abstract void validate(Order order);protected abstract void calculatePrice(Order order);protected void generateInvoice(Order order) {System.out.println("生成發票");}protected void sendNotification(Order order) {System.out.println("發送通知");}
}
4.2.2 具體類
// NormalOrderProcessor.java
public class NormalOrderProcessor extends OrderProcessor {@Overrideprotected void validate(Order order) {System.out.println("驗證普通訂單");}@Overrideprotected void calculatePrice(Order order) {System.out.println("計算普通訂單價格");}
}// PromotionOrderProcessor.java
public class PromotionOrderProcessor extends OrderProcessor {@Overrideprotected void validate(Order order) {System.out.println("驗證促銷訂單");}@Overrideprotected void calculatePrice(Order order) {System.out.println("計算促銷訂單價格(含折扣)");}
}
4.2.3 使用示例
public class OrderProcessorTest {public static void main(String[] args) {Order order = new Order();OrderProcessor normalProcessor = new NormalOrderProcessor();normalProcessor.processOrder(order);System.out.println("----------");OrderProcessor promotionProcessor = new PromotionOrderProcessor();promotionProcessor.processOrder(order);}
}

輸出:

驗證普通訂單
計算普通訂單價格
生成發票
發送通知
----------
驗證促銷訂單
計算促銷訂單價格(含折扣)
生成發票
發送通知

與其他模式的關系

模式關系說明
策略模式(Strategy Pattern)相似但用途不同策略模式封裝算法,模板方法模式封裝算法骨架
工廠模式(Factory Pattern)可組合使用工廠模式用于創建對象,模板方法模式用于定義算法結構
命令模式(Command Pattern)不同但可結合使用命令模式封裝請求,模板方法模式控制算法流程

總結

5.1 本日學習要點

  • 模板方法模式的核心思想是將算法的骨架定義在父類中,將具體步驟延遲到子類中實現。
  • 通過模板方法,可以統一算法的執行流程,同時允許子類靈活調整部分步驟。
  • 模板方法模式適用于具有固定流程但部分步驟需定制的場景。
  • 通過完整 Java 示例,展示了模板方法模式的實現方式和實際應用。
  • 模板方法模式與策略模式、工廠模式等存在相似之處,但在應用場景上有明顯區別。

5.2 下一日預告

明天我們將進入“設計模式精講”系列的第23天,主題為【設計模式精講 Day 23】訪問者模式(Visitor Pattern)。我們將探討如何通過訪問者模式實現對對象結構的遍歷與操作,提升系統的靈活性和可擴展性。敬請期待!


進一步學習資料

  1. 《設計模式:可復用面向對象軟件的基礎》 —— GoF 經典著作
  2. 模板方法模式 - Wikipedia
  3. Java 設計模式之模板方法模式詳解
  4. Spring 框架中的模板方法模式應用
  5. 模板方法模式 vs 策略模式對比

【設計模式精講 Day 22】模板方法模式(Template Method Pattern) 已完成,歡迎轉發、收藏、評論交流。

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

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

相關文章

如何在pytorch中使用tqdm:優雅實現訓練進度監控

文章目錄 為什么需要進度條?tqdm 簡介基礎用法示例深度學習中的實戰應用1. 數據加載進度監控2. 訓練循環增強版3. 驗證階段集成 高級技巧與最佳實踐1. 自定義進度條樣式2. 嵌套進度條(多任務)3. 分布式訓練支持4. 與日志系統集成 性能優化建議…

Linux中的xxd命令詳解

xxd 是一個 十六進制轉儲(hex dump)工具,通常用于將二進制文件轉換為十六進制格式,或者反向轉換(十六進制→二進制)。它是 vim 的一部分,但在大多數 Linux 系統(如 Ubuntu&#xff0…

磐維數據庫panweidb3.1.0單節點多實例安裝

0 說明 業務科室提單需要在某臺主機上部署多個單機磐維數據庫,用于業務測試。以下內容展示如何在單節點安裝多個磐維數據庫實例。 1 部署環境準備 1.1 IP 地址及端口 instipport實例1192.168.131.1717700實例2192.168.131.1727700 在131.17上分別安裝兩個實例&…

轉錄組分析流程(三):功能富集分析

我們的教程主要是以一個具體的例子作為線索,通過對公共數據庫數據bulk-RNA-seq的挖掘,利用生物信息學分析來探索目標基因集作為某種疾病數據預后基因的潛能及其潛在分子機制,同時在單細胞水平分析(對scRNA-seq進行挖掘)預后基因的表達,了解細胞之間的通訊網絡,以期為該疾病…

全面掌握 tkinter:Python GUI 編程的入門與實戰指南

在自動化、工具開發、數據可視化等領域,圖形用戶界面(GUI)往往是提升用戶體驗的重要方式。作為 Python 官方內置的 GUI 庫,tkinter 以其輕量、跨平臺、易于學習的特性成為初學者和輕量級應用開發者首選。 本文將以深入淺出的方式…

TDH社區開發版安裝教程

(注:本文章來源于星環官網安裝手冊) 后面放置了視頻和安裝手冊連接 1、硬件及環境要求 Docker17及以上版本,支持Centos,Ubuntu等系統(注:這里我使用CentOS-7版本,最佳版本推薦為7.…

Linux基本命令篇 —— grep命令

grep是Linux/Unix系統中一個非常強大的文本搜索工具,它的名字來源于"Global Regular Expression Print"(全局正則表達式打印)。grep命令用于在文件中搜索包含特定模式的行,并將匹配的行打印出來。 目錄 一、基本語法 二…

蒼穹外賣問題系列之 蒼穹外賣訂單詳情前端界面和網課給的不一樣

問題 如圖,我的前端界面和網課里面給的不一樣,沒有“申請退款”和一些其他的該有的東西。 原因分析 “合計”這一欄顯示undefined說明我們的總金額沒有輸入進去。可以看看訂單提交那塊的代碼,是否可以正確輸出。還有就是訂單詳細界面展示這…

CppCon 2018 學習:EMULATING THE NINTENDO 3DS

我們來逐個分析一下這個 組件交互模型 和 仿真 & 序列化 的關系,特別是主線程(Main Thread)與其他系統組件之間的交互。 1. Main Thread — simple (basically memcpy) --> GPU Main Thread(主線程)負責游戲的…

[Python 基礎課程]數字

數字 數字數據類型用于存儲數值,比如整數、小數等。數據類型是不允許改變的,這就意味著如果改變數字數據類型的值,將重新分配內存空間。 創建數字類型的變量: var1 1 var2 10創建完變量后,如果想廢棄掉這個變量&a…

Linux CentOS環境下Java連接MySQL數據庫指南

文章目錄 前言一、環境準備1.1 系統更新1.2 Java環境安裝1.3 MySQL數據庫安裝1.4 下載JDBC驅動 二、編寫Java程序2.1 代碼如下2.2 編譯和運行2.3 驗證創建結果 三、代碼上傳至Gitee3.1 安裝配置Git3.2 克隆倉庫到本地3.3 添加Java項目文件3.4 提交代碼到本地倉庫3.5 推送到Gite…

LLM面試12

訊飛算法工程師面試題 SVM核函數能否映射到無窮維 可以的,多項式核函數將低維數據映射到高維(維度是有限的),而高斯核函數可以映射到無窮維。由 描述下xgb原理,損失函數 首先需要說一說GBDT,它是一種基于boosting增強…

類加載生命周期與內存區域詳解

類加載生命周期與內存區域詳解 Java 類加載的生命周期包括加載、驗證、準備、解析、初始化五個階段,每個階段在內存中的存儲區域和賦值機制各有不同。以下是詳細解析: 一、類加載生命周期階段 1. 加載(Loading) 內存區域&…

正交視圖三維重建2 筆記 2d線到3d線2 先生成3d線然后判斷3d線在不在

應該先連線再判斷線在不在 if(fx1tx1&&tx1tx2){ const A[fx1, fy1, ty1];const Ahat[fx1, fy1, ty2];drawlines(A[0], A[1], A[2], Ahat[0], Ahat[1], Ahat[2], lineId, type,2);}if(fx2tx1&&tx1tx2){ const B[fx2, fy2, ty1];const Bhat[fx2, fy2, ty2];drawl…

Hibernate對象生命周期全解析

Hibernate對象生命周期詳解 Hibernate作為Java領域主流的ORM框架,其核心機制之一就是對持久化對象生命周期的管理。理解Hibernate對象生命周期對于正確使用Hibernate進行數據持久化操作至關重要。Hibernate將對象分為三種主要狀態:瞬時態(Transient)、持久態(Persistent)和游…

MCP 協議使用核心講解

📄 MCP 協議使用核心講解 ? MCP 協議的核心在于以下幾個方面 一、MCP 請求結構(MCPRequest) {"messages": [{"role": "user","content": "幫我查詢一下上海的天氣"}],"tools"…

云計算中的幾何方法:曲面變形的可視化與動畫-AI云計算數值分析和代碼驗證

著重強調微分方程底層的幾何和代數結構,以進行更深入的分析和求解方法。開發結構保持的數值方法,以在計算中保持定性特征。統一符號和數值方法,實現有效的數學建模。利用幾何解釋(如雙曲幾何)求解經典微分方程。利用計…

OpenCV篇——項目(一)OCR識別讀取銀行卡號碼

目錄 信用卡數字識別系統:前言與代碼解析 前言 項目代碼 ??????結果演示 代碼模塊解析 1. 參數解析模塊 2. 輪廓排序函數 3. 圖像預處理模塊 4. 輸入圖像處理流程 5. 卡號區域定位 6. 數字識別與輸出 系統優勢 信用卡數字識別系統:前言…

Adobe AI高效設計秘籍與創新思維進階

開篇:十年設計征途,Adobe賦能創意飛翔 作為一名在設計領域耕耘十年的旅居職業設計師,我得益于英國帕維斯經濟與音樂學院(Parvis School of Economics and Music)提供的Adobe正版教育訂閱,得以持續探索技術…

vc formal實例

命令: module load gui 方式啟動命令, 看一下cc_pinmux.tcl 里面有什么: 工具feature 的設置,不太懂 對特定模塊做blackbox, library file, 一般是工具無法識別的模塊,例如 IO lib,memory lib,analog lib, 內部有 …