设计模式 - 行为模式_Template Method Pattern模板方法模式在数据处理中的应用
文章目录
- 概述
- 1. 核心思想
- 2. 结构
- 3. 示例代码
- 4. 优点
- 5. 缺点
- 6. 适用场景
- 7. 案例:模板方法模式在数据处理中的应用
- 案例背景
- UML
- 搭建抽象基类 - 数据处理的 “总指挥”
- 子类定制 - 适配不同供应商
- 供应商 A 的数据处理器
- 供应商 B 的数据处理器
- 在业务代码中整合运用
- 8. 总结

概述
模板方法模式(Template Method Pattern)是一种行为设计模式,其核心思想是:定义一个操作的算法骨架,将一些步骤的实现延迟到子类中。在软件设计中,模板方法模式通常用于处理一系列相似的操作,这些操作可以被抽象为固定的流程,而流程中的某些步骤则由子类来具体实现。
1. 核心思想
模板方法模式的核心思想可以总结为以下几点:
- 固定流程:定义一个固定的算法流程,确保所有子类都遵循相同的步骤。
- 可变步骤:将某些步骤的具体实现延迟到子类中,允许子类根据需求定制。
- 代码复用:通过将通用逻辑放在父类中,减少代码重复。
2. 结构
模板方法模式通常由以下几个部分组成:
- 抽象类(Abstract Class):定义算法的骨架,并包含一些抽象方法供子类实现。
- 具体子类(Concrete Class):实现抽象类中的抽象方法,完成具体的业务逻辑。
- 模板方法(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. 案例:模板方法模式在数据处理中的应用
案例背景
我们的平台需要处理来自以下两个供应商的商品数据:
- 供应商 A:提供 JSON 格式的商品数据,需要对商品名称进行标准化处理。
- 供应商 B:提供 XML 格式的商品数据,需要对商品价格进行汇率转换。
尽管数据格式和处理逻辑不同,但整体的处理流程是相同的,包括以下步骤:
- 数据验证:验证数据的完整性和合法性。
- 数据解析:将原始数据解析为内部数据结构。
- 数据处理:根据业务需求对数据进行处理。
- 数据存储:将处理后的数据存储到数据库中。
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. 总结
模板方法模式通过定义算法的骨架并将某些步骤的具体实现延迟到子类中,提供了一种灵活且可扩展的设计方式。它在代码复用、扩展性和灵活性方面具有显著优势,适用于需要固定流程但允许部分步骤自定义的场景。通过合理使用模板方法模式,可以构建出清晰、可维护且易于扩展的代码架构。

相关文章:
设计模式 - 行为模式_Template Method Pattern模板方法模式在数据处理中的应用
文章目录 概述1. 核心思想2. 结构3. 示例代码4. 优点5. 缺点6. 适用场景7. 案例:模板方法模式在数据处理中的应用案例背景UML搭建抽象基类 - 数据处理的 “总指挥”子类定制 - 适配不同供应商供应商 A 的数据处理器供应商 B 的数据处理器 在业务代码中整合运用 8. 总…...
新春登蛇山:告别岁月,启航未来
大年初一,晨曦透过薄雾,温柔地洒在武汉的大街小巷。2025 年的蛇年春节,带着新春的喜气与希望悄然而至。我站在蛇山脚下,心中涌动着复杂的情感,因为今天,我不仅将与家人一起登山揽胜,更将在这一天…...
hive:基本数据类型,关于表和列语法
基本数据类型 Hive 的数据类型分为基本数据类型和复杂数据类型 加粗的是常用数据类型 BOOLEAN出现ture和false外的其他值会变成NULL值 没有number,decimal类似number 如果输入的数据不符合数据类型, 映射时会变成NULL, 但是数据本身并没有被修改 创建表 创建表的本质其实就是在…...
安装最小化的CentOS7后,执行yum命令报错Could not resolve host mirrorlist.centos.org; 未知的错误
文章目录 安装最小化的CentOS7后,执行yum命令报错"Could not resolve host: mirrorlist.centos.org; 未知的错误"错误解决方案: 安装最小化的CentOS7后,执行yum命令报错"Could not resolve host: mirrorlist.centos.org; 未知…...
图论——spfa判负环
负环 图 G G G中存在一个回路,该回路边权之和为负数,称之为负环。 spfa求负环 方法1:统计每个点入队次数, 如果某个点入队n次, 说明存在负环。 证明:一个点入队n次,即被更新了n次。一个点每次被更新时所对应最短路的边数一定是…...
软件工程概论试题三
一、单选 1.需求确认主要检査五个方面的内容,其中那一项是为了保证文档中的需求不互相冲突(即不应该有相互矛盾的约束或者对同一个系统功能有不同的描述)。 A.现实性 B. 可验证性 C.一致性 D.正确性 E.完整性 正答:C 2.下列开发方法中,( )不…...
21.3-启动流程、编码风格(了解) 第21章-FreeRTOS项目实战--基础知识之新建任务、启动流程、编码风格、系统配置 文件组成和编码风格(了解)
21.3-启动流程、编码风格(了解) 启动流程 第一种启动流程(我们就使用这个): 在main函数中将硬件初始化、RTOS系统初始化,同时创建所有任务,再启动RTOS调度器。 第二种启动流程: 在main函数中将硬件初始化、RTOS系统初始化,只…...
未来无线技术的发展方向
未来无线技术的发展趋势呈现出多样化、融合化的特点,涵盖速度、覆盖范围、应用领域、频段利用、安全性等多个方面。这些趋势将深刻改变人们的生活和社会的运行方式。 传输速度提升:Wi-Fi 技术迭代加快,如 Wi-Fi7 理论峰值速率达 46Gbps&#…...
Qt5离线安装包无法下载问题解决办法
想在电脑里装一个Qt,但是直接报错。果然还是有解决办法滴。 qt download from your ip is not allowed Qt5安装包下载办法 方法一:简单直接,直接科学一下,不过违法行为咱不做,遵纪守法好公民(不过没办法阻…...
qt-C++笔记之QLine、QRect、QPainterPath、和自定义QGraphicsPathItem、QGraphicsRectItem的区别
qt-C笔记之QLine、QRect、QPainterPath、和自定义QGraphicsPathItem、QGraphicsRectItem的区别 code review! 参考笔记 1.qt-C笔记之重写QGraphicsItem的paint方法(自定义QGraphicsItem) 文章目录 qt-C笔记之QLine、QRect、QPainterPath、和自定义QGraphicsPathItem、QGraphic…...
doris:导入时实现数据转换
Doris 在数据导入时提供了强大的数据转换能力,可以简化部分数据处理流程,减少对额外 ETL 工具的依赖。主要支持以下四种转换方式: 列映射:将源数据列映射到目标表的不同列。 列变换:使用函数和表达式对源数据进行实时…...
新版231普通阿里滑块 自动化和逆向实现 分析
声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 逆向过程 补环境逆向 部分补环境 …...
如何构建树状的思维棱镜认知框架
在思维与知识管理中,“树状思维棱镜”通常指一种层级式、可多维度展开和不断深入(下钻)的认知框架。它不仅仅是普通的树状结构(如传统思维导图),更强调“棱镜”所体现的多视角、多维度切换与综合分析的能力…...
openRv1126 AI算法部署实战之——ONNX模型部署实战
在RV1126开发板上部署ONNX算法,实时目标检测RTSP传输。视频演示地址 rv1126 yolov5 实时目标检测 rtsp传输_哔哩哔哩_bilibili 一、准备工作 1.从官网下载YOLOv5-v7.0工程(YOLOv5的第7个版本) 手动在线下载: Releases ultraly…...
Vue 组件开发:构建高效可复用的前端界面要素
1 引言 在现代 Web 开发中,构建高效且可复用的前端界面要素是提升开发效率和用户体验的关键。Vue.js 作为一种轻量级且功能强大的前端框架,提供了丰富的工具和机制,帮助开发者快速构建高质量的应用程序。通过合理设计和封装 Vue 组件,我们可以实现组件的高效复用,提高开发…...
Vue.js组件开发-实现全屏平滑移动、自适应图片全屏滑动切换
使用Vue实现全屏平滑移动、自适应图片全屏滑动切换的功能。使用Vue 3和Vue Router,并结合一些CSS样式来完成这个效果。 步骤 创建Vue项目:使用Vue CLI创建一个新的Vue项目。准备图片:将需要展示的图片放在项目的public目录下。创建组件&…...
水果实体店品牌数字化:RWA + 智能体落地方案
一、方案背景 随着数字化技术的迅猛发展,实体零售行业正面临前所未有的挑战与机遇。传统的零售模式难以满足消费者对个性化、便捷化、智能化的需求,尤其是在水果等生鲜商品领域,如何通过技术手段提升运营效率、增强顾客体验、拓宽盈利模式&a…...
DeepSeek模型:开启人工智能的新篇章
DeepSeek模型:开启人工智能的新篇章 在当今快速发展的技术浪潮中,人工智能(AI)已经成为了推动社会进步和创新的核心力量之一。而DeepSeek模型,作为AI领域的一颗璀璨明珠,正以其强大的功能和灵活的用法&…...
Kubernetes 环境中的自动化运维实战指南
Kubernetes 作为容器编排领域的领导者,已经成为云原生应用的核心基础设施。然而,随着集群规模的扩大和应用的复杂化,手动运维 Kubernetes 集群变得愈发困难。自动化运维成为提升效率、保障系统稳定性的关键。本文将详细介绍如何在 Kubernetes 环境中实施自动化运维,涵盖工具…...
深入解析 C++17 中的 std::not_fn
文章目录 1. std::not_fn 的定义与目的2. 基本用法2.1 基本示例2.2 使用 Lambda 表达式2.3 与其他函数适配器的比较3. 在标准库中的应用3.1 结合标准库算法使用3.1.1 std::find_if 中的应用3.1.2 std::remove_if 中的应用3.1.3 其他标准库算法中的应用4. 高级技巧与最佳实践4.1…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
