設計模式 - 行為模式_Template Method Pattern模板方法模式在數據處理中的應用

文章目錄

  • 概述
  • 1. 核心思想
  • 2. 結構
  • 3. 示例代碼
  • 4. 優點
  • 5. 缺點
  • 6. 適用場景
  • 7. 案例:模板方法模式在數據處理中的應用
    • 案例背景
    • UML
    • 搭建抽象基類 - 數據處理的 “總指揮”
    • 子類定制 - 適配不同供應商
      • 供應商 A 的數據處理器
      • 供應商 B 的數據處理器
    • 在業務代碼中整合運用
  • 8. 總結

在這里插入圖片描述


概述

模板方法模式(Template Method Pattern)是一種行為設計模式,其核心思想是:定義一個操作的算法骨架,將一些步驟的實現延遲到子類中。在軟件設計中,模板方法模式通常用于處理一系列相似的操作,這些操作可以被抽象為固定的流程,而流程中的某些步驟則由子類來具體實現。


1. 核心思想

模板方法模式的核心思想可以總結為以下幾點:

  • 固定流程:定義一個固定的算法流程,確保所有子類都遵循相同的步驟。
  • 可變步驟:將某些步驟的具體實現延遲到子類中,允許子類根據需求定制。
  • 代碼復用:通過將通用邏輯放在父類中,減少代碼重復。

2. 結構

模板方法模式通常由以下幾個部分組成:

  1. 抽象類(Abstract Class):定義算法的骨架,并包含一些抽象方法供子類實現。
  2. 具體子類(Concrete Class):實現抽象類中的抽象方法,完成具體的業務邏輯。
  3. 模板方法(Template Method):在抽象類中定義的一個方法,它調用了算法中的各個步驟。

3. 示例代碼

一個簡單的模板方法模式示例,展示如何定義一個算法骨架并在子類中實現具體步驟。

// 抽象類
abstract class AbstractClass {// 模板方法,定義了算法的骨架public final void templateMethod() {step1();step2();step3();}// 具體方法,子類可以直接使用private void step1() {System.out.println("執行步驟1");}// 抽象方法,子類需要實現protected abstract void step2();// 鉤子方法,子類可以選擇性重寫protected void step3() {System.out.println("執行步驟3");}
}// 具體子類A
class ConcreteClassA extends AbstractClass {@Overrideprotected void step2() {System.out.println("ConcreteClassA 執行步驟2");}
}// 具體子類B
class ConcreteClassB extends AbstractClass {@Overrideprotected void step2() {System.out.println("ConcreteClassB 執行步驟2");}@Overrideprotected void step3() {System.out.println("ConcreteClassB 執行步驟3");}
}// 客戶端代碼
public class TemplateMethodPatternDemo {public static void main(String[] args) {AbstractClass classA = new ConcreteClassA();classA.templateMethod();AbstractClass classB = new ConcreteClassB();classB.templateMethod();}
}

為了防止惡意修改,模板方法通常使用final關鍵字修飾,避免被子類重寫。


4. 優點

  • 代碼復用:通過將通用邏輯放在父類中,減少了代碼重復。
  • 擴展性:子類可以通過實現抽象方法來擴展算法的某些步驟,而無需修改算法的整體結構。
  • 靈活性:鉤子方法(Hook Method)允許子類選擇性地覆蓋某些步驟,增加了靈活性。

5. 缺點

  • 復雜性:如果算法的步驟過多,可能會導致類的層次結構變得復雜。
  • 限制性:模板方法模式要求算法的步驟是固定的,這可能會限制某些場景下的靈活性。

6. 適用場景

  • 固定流程:當某個算法的流程是固定的,但某些步驟的具體實現可能不同時,可以使用模板方法模式。
  • 代碼復用:當多個子類有共同的邏輯時,可以將這些邏輯提取到父類中,減少代碼重復。
  • 框架設計:在框架設計中,模板方法模式常用于定義框架的核心流程,而將具體實現留給用戶自定義。

7. 案例:模板方法模式在數據處理中的應用

案例背景

我們的平臺需要處理來自以下兩個供應商的商品數據:

  1. 供應商 A:提供 JSON 格式的商品數據,需要對商品名稱進行標準化處理。
  2. 供應商 B:提供 XML 格式的商品數據,需要對商品價格進行匯率轉換。

盡管數據格式和處理邏輯不同,但整體的處理流程是相同的,包括以下步驟:

  1. 數據驗證:驗證數據的完整性和合法性。
  2. 數據解析:將原始數據解析為內部數據結構。
  3. 數據處理:根據業務需求對數據進行處理。
  4. 數據存儲:將處理后的數據存儲到數據庫中。

UML

在這里插入圖片描述

搭建抽象基類 - 數據處理的 “總指揮”

首先,我們創建一個抽象的基類 AbstractProductDataHandler,它將定義整個數據處理流程的骨架。

public abstract class AbstractProductDataHandler {// 模板方法,定義了數據處理的固定流程public final void handleProductData(String rawData) {if (validateData(rawData)) {logStart(rawData);Product product = parseData(rawData);processProduct(product);saveProduct(product);logCompletion(product);} else {handleValidationFailure(rawData);}}// 抽象方法,子類需要實現數據驗證邏輯protected abstract boolean validateData(String rawData);// 抽象方法,子類需要實現數據解析邏輯protected abstract Product parseData(String rawData);// 抽象方法,子類需要實現數據處理邏輯protected abstract void processProduct(Product product);// 具體方法,通用的數據存儲邏輯private void saveProduct(Product product) {System.out.println("保存商品數據:" + product);// 實際項目中,這里會調用數據庫操作}// 具體方法,記錄處理開始日志private void logStart(String rawData) {System.out.println("開始處理商品數據,來源:" + getSource());}// 具體方法,記錄處理完成日志private void logCompletion(Product product) {System.out.println("商品數據處理完成,結果:" + product);}// 具體方法,處理驗證失敗的情況protected void handleValidationFailure(String rawData) {System.out.println("數據驗證失敗:" + rawData);}// 抽象方法,子類需要實現以返回數據來源protected abstract String getSource();
}

子類定制 - 適配不同供應商

接下來,我們為每個供應商創建具體的子類,實現抽象基類中的抽象方法。

供應商 A 的數據處理器

@Component
public class SupplierADataHandler extends AbstractProductDataHandler {@Overrideprotected boolean validateData(String rawData) {// 簡單的 JSON 格式驗證return rawData != null && rawData.startsWith("{") && rawData.endsWith("}");}@Overrideprotected Product parseData(String rawData) {// 解析 JSON 數據// 實際項目中,可以使用 Jackson 或 Gson 等庫Product product = new Product();product.setName("SupplierA Product");product.setPrice(100.0);return product;}@Overrideprotected void processProduct(Product product) {// 對商品名稱進行標準化處理product.setName(product.getName().toUpperCase());}@Overrideprotected String getSource() {return "Supplier A";}
}

供應商 B 的數據處理器

@Component
public class SupplierBDataHandler extends AbstractProductDataHandler {@Overrideprotected boolean validateData(String rawData) {// 簡單的 XML 格式驗證return rawData != null && rawData.startsWith("<") && rawData.endsWith(">");}@Overrideprotected Product parseData(String rawData) {// 解析 XML 數據// 實際項目中,可以使用 JAXB 或 DOM 解析器Product product = new Product();product.setName("SupplierB Product");product.setPrice(200.0);return product;}@Overrideprotected void processProduct(Product product) {// 對商品價格進行匯率轉換product.setPrice(product.getPrice() * 0.85); // 假設匯率為 0.85}@Overrideprotected String getSource() {return "Supplier B";}
}

在業務代碼中整合運用

最后,我們在業務代碼中使用這些數據處理器。通過 Spring 的依賴注入機制,我們可以輕松地切換不同的處理器。

@Service
public class ProductDataProcessingService {@Autowiredprivate SupplierADataHandler supplierAHandler;@Autowiredprivate SupplierBDataHandler supplierBHandler;public void processDataFromSupplierA(String rawData) {supplierAHandler.handleProductData(rawData);}public void processDataFromSupplierB(String rawData) {supplierBHandler.handleProductData(rawData);}
}

8. 總結

模板方法模式通過定義算法的骨架并將某些步驟的具體實現延遲到子類中,提供了一種靈活且可擴展的設計方式。它在代碼復用、擴展性和靈活性方面具有顯著優勢,適用于需要固定流程但允許部分步驟自定義的場景。通過合理使用模板方法模式,可以構建出清晰、可維護且易于擴展的代碼架構。
在這里插入圖片描述

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

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

相關文章

HTML5+SVG+CSS3實現雪中點亮的圣誕樹動畫效果源碼

源碼介紹 這是一款基于HTML5SVGCSS3實現雪中點亮的圣誕樹動畫效果源碼。畫面中的圣誕樹矗立在雪地中&#xff0c;天上飄落著雪花。當鼠標滑過圣誕樹時&#xff0c;可見到圣誕樹上的燈光閃爍&#xff0c;同時左下角探出雪怪模樣的半個腦袋&#xff0c;四處張望著。整體畫面栩栩…

C基礎寒假練習(3)

一、求數組中的第二大值 #include <stdio.h> int main() {int arr[] {12, 35, 1, 10, 34, 1};int size sizeof(arr) / sizeof(arr[0]);if (size < 2) {printf("數組元素不足兩個\n");return 0;}int first -2147483648, second -2147483648; // 使用IN…

【linux三劍客】grep練習題

題目 進入/lianxi目錄&#xff0c;復制/etc/passwd到當前目錄下&#xff0c;然后對passwd進行操作查找出當前passwd文件中以ftp或者mail開頭的行&#xff0c;在屏幕上輸出。查找出當前passwd文件中有沒有以r、m、f開頭的行&#xff0c;在屏幕上輸出。查找出當前passwd文件中以…

C++,STL,【目錄篇】

文章目錄 一、簡介二、內容提綱第一部分&#xff1a;STL 概述第二部分&#xff1a;STL 容器第三部分&#xff1a;STL 迭代器第四部分&#xff1a;STL 算法第五部分&#xff1a;STL 函數對象第六部分&#xff1a;STL 高級主題第七部分&#xff1a;STL 實戰應用 三、寫作風格四、…

【Node.js】Koa2 整合接口文檔

部分學習來源&#xff1a;https://blog.csdn.net/qq_38734862/article/details/107715579 依賴 // koa2-swagger-ui UI視圖組件 swagger-jsdoc 識別寫的 /***/ 轉 json npm install koa2-swagger-ui swagger-jsdoc --save配置 config\swaggerConfig.js const Router requir…

Maven的單元測試

1. 單元測試的基本概念 單元測試&#xff08;Unit Testing&#xff09; 是一種軟件測試方法&#xff0c;專注于測試程序中的最小可測試單元——通常是單個類或方法。通過單元測試&#xff0c;可以確保每個模塊按預期工作&#xff0c;從而提高代碼的質量和可靠性。 2.安裝和配…

論文閱讀(八):結構方程模型用于研究數量遺傳學中的因果表型網絡

1.論文鏈接&#xff1a;Structural Equation Models for Studying Causal Phenotype Networks in Quantitative Genetics 摘要&#xff1a; 表型性狀可能在它們之間發揮因果作用。例如&#xff0c;農業物種的高產可能會增加某些疾病的易感性&#xff0c;相反&#xff0c;疾病的…

LeetCode | 不同路徑

一個機器人位于一個 m x n 網格的左上角 &#xff08;起始點在下圖中標記為 “Start” &#xff09;。 機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角&#xff08;在下圖中標記為 “Finish” &#xff09;。 問總共有多少條不同的路徑&#xff1f; 示例 1…

C++的類Class

文章目錄 一、C的struct和C的類的區別二、關于OOP三、舉例&#xff1a;一個商品類CGoods四、構造函數和析構函數1、定義一個順序棧2、用構造和析構代替s.init(5);和s.release();3、在不同內存區域構造對象4、深拷貝和淺拷貝5、構造函數和深拷貝的簡單應用6、構造函數的初始化列…

Excel 技巧21 - Excel中整理美化數據實例,Ctrl+T 超級表格(★★★)

本文講Excel中如何整理美化數據的實例&#xff0c;以及CtrlT 超級表格的常用功能。 目錄 1&#xff0c;Excel中整理美化數據 1-1&#xff0c;設置間隔行顏色 1-2&#xff0c;給總銷量列設置數據條 1-3&#xff0c;根據總銷量設置排序 1-4&#xff0c;加一個銷售趨勢列 2&…

Leetcode 131 分割回文串(純DFS)

131. 分割回文串https://leetcode.cn/problems/palindrome-partitioning/https://leetcode.cn/problems/palindrome-partitioning/ 給你一個字符串 s&#xff0c;請你將 s 分割成一些子串&#xff0c;使每個子串都是 回文串 。返回 s 所有可能的分割方案。 示例 1&#xff1a…

電梯系統的UML文檔14

對于 HallButtonControl&#xff0c;我們有二個狀態: "門廳燈開 " 和 " 門廳燈關"。 從給出的初始信息&#xff0c;初始的狀態應該是"門廳燈關"。行為定義&#xff1a; " 當 HallCall[f&#xff0c;d]是真&#xff0c;則指令 HallLight[f&…

關于安卓greendao打包時報錯問題修復

背景 項目在使用greendao的時候&#xff0c;debug安裝沒有問題&#xff0c;一到打包簽名就報了。 環境 win10 jdk17 gradle8 項目依賴情況 博主的greendao是一個獨立的module項目&#xff0c;項目目前只適配了java&#xff0c;不支持Kotlin。然后被外部集成。greendao版本…

SQL server 數據庫使用整理

標題&#xff1a;SQL server 數據庫使用整理 1.字符串表名多次查詢 2.讀取SQL中Json字段中的值&#xff1a;JSON_VALUE&#xff08;最新版本支持&#xff0c;屬性名大小寫敏感&#xff09; 1.字符串表名多次查詢 SELECT ROW_NUMBER() OVER (ORDER BY value ASC) rowid,value…

一文講解Java中的BIO、NIO、AIO之間的區別

BIO、NIO、AIO是Java中常見的三種IO模型 BIO&#xff1a;采用阻塞式I/O模型&#xff0c;線程在執行I/O操作時被阻塞&#xff0c;無法處理其他任務&#xff0c;適用于連接數比較少的場景&#xff1b;NIO&#xff1a;采用非阻塞 I/O 模型&#xff0c;線程在等待 I/O 時可執行其…

分布式系統架構怎么搭建?

分布式系統架構 互聯網企業的業務飛速發展&#xff0c;促使系統架構不斷變化。總體來說&#xff0c;系統架構大致經歷了單體應用架構—垂直應用架構—分布式架構—SOA架構—微服務架構的演變&#xff0c;很多互聯網企業的系統架構已經向服務化網格&#xff08;Service Mesh&am…

Effective C++ 規則50:了解 new 和 delete 的合理替換時機

1、背景 在 C 中&#xff0c;new 和 delete 是動態分配內存的核心操作符。然而&#xff0c;直接使用它們有時會增加程序的復雜性&#xff0c;甚至導致內存泄漏和其他問題。因此&#xff0c;了解何時替換 new 和 delete 并選擇更適合的內存管理策略&#xff0c;是編寫高效、健壯…

Effective Python:(10)

Effective Python提供90條新穎的Python3編程技巧&#xff0c;可以讓我們寫程序更加靈活&#xff0c;代碼更加整潔而易于維護&#xff0c;這對于商業化系統代碼的重要性不言而喻。 前面兩條主要介紹切片的實用好玩的用法&#xff0c;這一條里反而建議不用切片&#xff0c;這是什…

高效學習方法分享

高效學習方法分享 引言 在信息高速發展的今天&#xff0c;學習已經成為每個人不可或缺的一部分。你是否曾感到學習的疲憊&#xff0c;信息的爆炸讓你無從下手&#xff1f;今天&#xff0c;我們將探討幾種高效的學習方法&#xff0c;幫助你從中找到適合自己的學習之道。關于學…

數據庫備份、主從、集群等配置

數據庫備份、主從、集群等配置 1 MySQL1.1 docker安裝MySQL1.2 主從復制1.2.1 主節點配置1.2.2 從節點配置1.2.3 創建用于主從同步的用戶1.2.4 開啟主從同步1.2.4 主從同步驗證 1.3 主從切換1.3.1 主節點設置只讀&#xff08;在192.168.1.151上操作&#xff09;1.3.2 檢查主從數…