设计模式 - 行为模式_Template Method Pattern模板方法模式在数据处理中的应用

server/2025/2/3 8:34:50/

文章目录

  • 概述
  • 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.ppmy.cn/server/164565.html

相关文章

Heptagon record 数据结构

Heptagon 语言支持 record 数据结构。record 数据结构与 Scade struct 数据结构相似。对 record 结构的操作支持结构构造、record 成员访问&#xff0c;record 成员修改。 record 结构构造的形式如 {f1 val; f2; val2}。使用样例如 typet {f1:int; f2:bool} fun recordDef(…

CSS 图像、媒体和表单元素的样式化指南

CSS 图像、媒体和表单元素的样式化指南 1. 替换元素&#xff1a;图像和视频1.1 调整图像大小示例代码&#xff1a;调整图像大小 1.2 使用 object-fit 控制图像显示示例代码&#xff1a;使用 object-fit 2. 布局中的替换元素示例代码&#xff1a;Grid 布局中的图像 3. 表单元素的…

Echarts 封装通用组件

目录结构 相关文件可以去我的 gitee 下载&#xff1a;https://gitee.com/hao-xiugong/management-vue-ts index.ts import BaseEcharts from "/components/page-echarts/src/base-echarts.vue"; import LineEcharts from "/components/page-echarts/src/line-e…

计算机网络 应用层 笔记 (电子邮件系统,SMTP,POP3,MIME,IMAP,万维网,HTTP,html)

电子邮件系统&#xff1a; SMTP协议 基本概念 工作原理 连接建立&#xff1a; 命令交互 客户端发送命令&#xff1a; 服务器响应&#xff1a; 邮件传输&#xff1a; 连接关闭&#xff1a; 主要命令 邮件发送流程 SMTP的缺点: MIME&#xff1a; POP3协议 基本概念…

聚簇索引、哈希索引、覆盖索引、索引分类、最左前缀原则、判断索引使用情况、索引失效条件、优化查询性能

聚簇索引 聚簇索引像一本按目录排版的书&#xff0c;用空间换时间&#xff0c;适合读多写少的场景。设计数据库时&#xff0c;主键的选择&#xff08;如自增ID vs 随机UUID&#xff09;会直接影响聚簇索引的性能。 什么是聚簇索引&#xff1f; 数据即索引&#xff1a;聚簇索引…

三天急速通关JavaWeb基础知识:Day 3 依赖管理项目构建工具Maven

三天急速通关JavaWeb基础知识&#xff1a;Day 3 依赖管理项目构建工具Maven 0 文章说明1 介绍2 安装与配置2.1 安装2.2 手动配置 3 创建Maven工程4 Maven构建工程5 Maven依赖管理6 Maven工程Build构建配置7 Maven依赖传递与依赖冲突7.1 依赖传递7.1 依赖冲突 8 Maven工程继承和…

【计算机网络】公有和私有 IP 地址

私有 IP 地址&#xff1a;私有 IP 地址&#xff1a; 定义 私有 IP 地址是专门为内部网络保留的 IP 地址范围&#xff0c;这些地址在互联网上不会被直接路由&#xff0c;仅用于内部网络中的设备之间的通信。私有 IP 地址范围如下&#xff1a; Class A&#xff1a;10.0.0.0 至 …

基础IO的学习

1. 理解文件 文件在磁盘里&#xff08;磁盘本身是外设&#xff09; 磁盘是永久性存储介质&#xff0c;文件在磁盘上的存储是永久的 磁盘是的文件 本质是对文件的所有操作&#xff0c;都是对外设的输入和输出 简称IO 对文件的操作本质是进程对文件的操作 磁盘的管理者是操作…