设计模式 - 行为模式_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.rhkb.cn/news/11571.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FlashAttention v1 论文解读

论文标题&#xff1a;FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness 论文地址&#xff1a;https://arxiv.org/pdf/2205.14135 FlashAttention 是一种重新排序注意力计算的算法&#xff0c;它无需任何近似即可加速注意力计算并减少内存占用。…

stm32硬件实现与w25qxx通信

使用的型号为stm32f103c8t6与w25q64。 STM32CubeMX配置与引脚衔接 根据stm32f103c8t6引脚手册&#xff0c;采用B12-B15四个引脚与W25Q64连接&#xff0c;实现SPI通信。 W25Q64SCK&#xff08;CLK&#xff09;PB13MOSI&#xff08;DI&#xff09;PB15MISO(DO)PB14CS&#xff08…

软件工程概论试题五

一、多选 1.好的软件的基本属性包括()。 A. 效率 B. 可依赖性和信息安全性 C. 可维护性 D.可接受性 正答&#xff1a;ABCD 2.软件工程的三要素是什么()? A. 结构化 B. 工具 C.面向对象 D.数据流! E.方法 F.过程 正答&#xff1a;BEF 3.下面中英文术语对照哪些是正确的、且是属…

FBX SDK的使用:基础知识

Windows环境配置 FBX SDK安装后&#xff0c;目录下有三个文件夹&#xff1a; include 头文件lib 编译的二进制库&#xff0c;根据你项目的配置去包含相应的库samples 官方使用案列 动态链接 libfbxsdk.dll, libfbxsdk.lib是动态库&#xff0c;需要在配置属性->C/C->预…

知识库管理在提升企业决策效率与知识共享中的应用探讨

内容概要 知识库管理是指企业对内部知识、信息进行系统化整理和管理的过程&#xff0c;其重要性在于为企业决策提供了坚实的数据支持与参考依据。知识库管理不仅能够提高信息的获取速度&#xff0c;还能有效减少重复劳动&#xff0c;提升工作效率。在如今快速变化的商业环境中…

基于vue船运物流管理系统设计与实现(源码+数据库+文档)

船运物流管理系统目录 目录 基于springboot船运物流管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员登录 2、货运单管理 3、公告管理 4、公告类型管理 5、新闻管理 6、新闻类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考…

【自然语言处理(NLP)】深度学习架构:Transformer 原理及代码实现

文章目录 介绍Transformer核心组件架构图编码器&#xff08;Encoder&#xff09;解码器&#xff08;Decoder&#xff09; 优点应用代码实现导包基于位置的前馈网络残差连接后进行层规范化编码器 Block编码器解码器 Block解码器训练预测 个人主页&#xff1a;道友老李 欢迎加入社…

Spring Boot 实例解析:配置文件

SpringBoot 的热部署&#xff1a; Spring 为开发者提供了一个名为 spring-boot-devtools 的模块来使用 SpringBoot 应用支持热部署&#xff0c;提高开发者的效率&#xff0c;无需手动重启 SpringBoot 应用引入依赖&#xff1a; <dependency> <groupId>org.springfr…

Linux网络 HTTPS 协议原理

概念 HTTPS 也是一个应用层协议&#xff0c;不过 是在 HTTP 协议的基础上引入了一个加密层。因为 HTTP的内容是明文传输的&#xff0c;明文数据会经过路由器、wifi 热点、通信服务运营商、代理服务器等多个物理节点&#xff0c;如果信息在传输过程中被劫持&#xff0c;传输的…

java练习(5)

ps:题目来自力扣 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这…

深入 Rollup:从入门到精通(三)Rollup CLI命令行实战

准备阶段&#xff1a;初始化项目 初始化项目&#xff0c;这里使用的是pnpm&#xff0c;也可以使用yarn或者npm # npm npm init -y # yarn yarn init -y # pnpm pnpm init安装rollup # npm npm install rollup -D # yarn yarn add rollup -D # pnpm pnpm install rollup -D在…

MySQL数据库环境搭建

下载MySQL 官网&#xff1a;https://downloads.mysql.com/archives/installer/ 下载社区版就行了。 安装流程 看b站大佬的视频吧&#xff1a;https://www.bilibili.com/video/BV12q4y1477i/?spm_id_from333.337.search-card.all.click&vd_source37dfd298d2133f3e1f3e3c…

松灵机器人 scout ros2 驱动 安装

必须使用 ubuntu22 必须使用 链接的humble版本 #打开can 口 sudo modprobe gs_usbsudo ip link set can0 up type can bitrate 500000sudo ip link set can0 up type can bitrate 500000sudo apt install can-utilscandump can0mkdir -p ~/ros2_ws/srccd ~/ros2_ws/src git cl…

【最长上升子序列Ⅱ——树状数组,二分+DP,纯DP】

题目 代码&#xff08;只给出树状数组的&#xff09; #include <bits/stdc.h> using namespace std; const int N 1e510; int n, m; int a[N], b[N], f[N], tr[N]; //f[i]表示以a[i]为尾的LIS的最大长度 void init() {sort(b1, bn1);m unique(b1, bn1) - b - 1;for(in…

Linux安装zookeeper

1, 下载 Apache ZooKeeperhttps://zookeeper.apache.org/releases.htmlhttps://zookeeper.apache.org/releases.htmlhttps://zookeeper.apache.org/releases.htmlhttps://zookeeper.apache.org/releases.htmlhttps://zookeeper.apache.org/releases.htmlhttps://zookeeper.apa…

day6手机摄影社区,可以去苹果摄影社区学习拍摄技巧

逛自己手机的社区&#xff1a;即&#xff08;手机牌子&#xff09;摄影社区 拍照时防止抖动可以控制自己的呼吸&#xff0c;不要大喘气 拍一张照片后&#xff0c;如何简单的用手机修图&#xff1f; HDR模式就是让高光部分和阴影部分更协调&#xff08;拍风紧时可以打开&…

linux本地部署deepseek-R1模型

国产开源大模型追平甚至超越了CloseAI的o1模型&#xff0c;大国崛起时刻&#xff01;&#xff01;&#xff01; DeepSeek R1 本地部署指南   在人工智能技术飞速发展的今天&#xff0c;本地部署AI模型成为越来越多开发者和企业关注的焦点。本文将详细介绍如何在本地部署DeepS…

小程序-基础加强-自定义组件

前言 这次讲自定义组件 1. 准备今天要用到的项目 2. 初步创建并使用自定义组件 这样就成功在home中引入了test组件 在json中引用了这个组件才能用这个组件 现在我们来实现全局引用组件 在app.json这样使用就可以了 3. 自定义组件的样式 发现页面里面的文本和组件里面的文…

c语言(关键字)

前言&#xff1a; 感谢b站鹏哥c语言 内容&#xff1a; 栈区&#xff08;存放局部变量&#xff09; 堆区 静态区&#xff08;存放静态变量&#xff09; rigister关键字 寄存器&#xff0c;cpu优先从寄存器里边读取数据 #include <stdio.h>//typedef&#xff0c;类型…

【最长不下降子序列——树状数组、线段树、LIS】

题目 代码 #include <bits/stdc.h> using namespace std; const int N 1e510; int a[N], b[N], tr[N];//a保存权值&#xff0c;b保存索引,tr保存f&#xff0c;g前缀属性最大值 int f[N], g[N]; int n, m; bool cmp(int x, int y) {if(a[x] ! a[y]) return a[x] < a[…