23种设计模式-行为型模式-模板方法

文章目录

  • 简介
  • 场景
  • 解决
    • 代码
    • 关键优化点
  • 总结

简介

模板方法是一种行为设计模式,它在超类中定义了一个算法的框架,允许子类在不修改结构的情况下重写算法的特定步骤。

场景

假如你正在开发一款分析文档的数据挖掘程序。用户需要向程序输入各种格式(PDF、DOC 或 CSV)的文档,程序会试图从这些文件中提取有意义的数据,再以统一的格式返回给用户。
程序的首个版本只支持 DOC 文件。下个版本,程序需要支持 CSV 文件。一个月后,程序又需要从 PDF 文件中抽取数据。
数据挖掘类中包含许多重复代码。
一段时间后,你发现这三个类中包含许多相似代码。尽管读取不同格式数据的代码完全不同,但数据处理和分析的代码却几乎完全一样。怎么在保持算法结构完整的情况下去除重复代码?这是第一个问题。
还有另一个与使用这些类的客户端代码相关的问题:客户端代码中包含许多条件语句,因为它要根据不同的文档类型选择合适的处理过程。 如果所有处理数据的类都有相同的接口或基类,那你就可以去除客户端代码里的条件语句,转而使用多态机制来调用处理对象的方法。

解决

模板方法模式建议把算法分解为一系列步骤,然后将这些步骤改写为方法,最后在“模板方法”中依次调用这些方法。步骤可以是抽象的,也可以有一些默认的实现。为了能够使用算法,客户端需要自己提供子类,并且实现所有的抽象步骤。可能还需重写一些步骤(但这一步中不包括模板方法自身)。
让我们想想怎么在数据挖掘程序里运用这样的方案。我们可为三个解析算法创建一个基类,这个类定义了一个模板方法-mine方法,这个方法会在内部调用不同的文档处理步骤。
模板方法将算法分解为步骤,并允许子类重写这些步骤,而非重写实际的模板方法。

首先,我们将所有步骤声明为抽象类型,强制要求子类自行实现这些方法。在我们的例子里,子类已经实现了必须的方法,因此我们只需调整这些方法的名称,让他跟超类的方法匹配就行了。
现在,让我们看看怎么去除子类里的重复代码。对于不同的文件格式,打开和关闭文件以及读取解析数据的代码都不同,所以不需要修改这些方法。但分析原始数据和生成报告等其他步骤的实现方式非常相似,所以可以把他们提取到基类里,让子类共享这些代码。
所以我们有两种类型的步骤:

  1. 抽象步骤必须由各个子类来实现
  2. 可选步骤已经有一些默认实现,但你仍然可以在需要时进行重写
    还有另一种名为钩子 hook 的步骤。钩子是内容为空的可选的步骤。即使子类不重写钩子,模板方法也能工作。钩子通常放置在算法重要步骤的前后,为子类提供额外的算法扩展点。

代码

// 抽象类定义模板方法
abstract class DataMiner {// 模板方法(不可被覆盖)public final void processDocument() {  openDocument();extractRawData();parseData();           // 抽象步骤analyzeData();         // 通用实现generateReport();      // Hook方法}// 文档打开基础实现protected void openDocument() {  System.out.println("打开文档...");}// 数据抽取基础实现protected void extractRawData() {  System.out.println("抽取原始数据...");}// 解析算法必须子类实现protected abstract void parseData();  // 通用分析实现protected void analyzeData() {  System.out.println("执行数据聚类分析...");}/* 钩子方法(可选覆盖) */protected void generateReport() {  System.out.println("生成基础统计报表");}
}// 具体子类实现
class PDFDataMiner extends DataMiner {@Overrideprotected void parseData() {  // 实现特定解析逻辑System.out.println("解析PDF版式结构");System.out.println("提取PDF文本流");}
}class CSVDataMiner extends DataMiner {@Overrideprotected void parseData() {  System.out.println("识别CSV分隔符");System.out.println("映射CSV字段");}@Overrideprotected void generateReport() {  // 自定义Hook实现super.generateReport();System.out.println("追加CSV格式验证结果");}
}// 客户端调用示例
class Client {public static void main(String[] args) {System.out.println("处理PDF文档:");DataMiner pdfProcessor = new PDFDataMiner();pdfProcessor.processDocument();  // 执行完整流程System.out.println("\n处理CSV文档:");DataMiner csvProcessor = new CSVDataMiner();csvProcessor.processDocument();}
}

关键优化点

  1. 固定流程:不可重写的processDocument()确保流程一致
  2. 职责分离:各子类仅需实现格式相关解析逻辑
  3. 扩展能力:通过钩子方法实现可选扩展(如CSV格式验证)

总结

在这里插入图片描述

  1. 抽象类(Abstract­Class)会声明算法步骤的方法(step1,step2…),以及依次调用它们的模板方法(templateMethod)。算法步骤可以被声明为抽象类型,也可以提供一些默认实现。
  2. 具体类(Con­crete­Class)可以重写所有步骤,但不能重写模板方法自身。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/900772.shtml

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

相关文章

解决Long类型前端精度丢失和正常传回后端问题

在 Java 后端开发中,可能会遇到前后端交互过程中 Long 类型精度丢失的问题。尤其是在 JavaScript 中,由于其 Number 类型是双精度浮点数,超过 16 位的 Long 类型值就会发生精度丢失。 问题背景 假设有如下实体类: public class…

PowerPhotos:拯救你的Mac照片库,告别苹果原生应用的局限

如果你用Mac管理照片,大概率被苹果原生「照片」应用折磨过——无法真正并行操作多个图库。每次切换图库都要关闭重启,想合并照片得手动导出导入,重复文件更是无处可逃…… 直到我发现了 PowerPhotos,这款专为Mac设计的照片库管理…

android 14.0 工厂模式 测试音频的一些问题(高通)

1之前用tinycap,现在得用agmcap 执行----agmcap /data/test.wav -D 100 -d 101 -i CODEC_DMA-LPAIF_RXTX-TX-3 -T 3 报错1 agmcap data/test.wav -D 100 -d 101 -i CODEC_DMA-LPAIF_RXTX-TX-3 -T 3 Failed to open xml file name /vendor/etc/backend_co…

以库存系统为核心的ERP底层架构设计

在企业资源计划(ERP)系统中,库存系统常被视为基础模块。但在现代企业的数字化进程中,库存系统不仅仅是一个模块,它已经逐步演化为驱动整个ERP生态的核心引擎。本文从架构设计的角度,探讨为何库存系统应被置…

辛格迪客户案例 | 北京舒曼德医药实施电子合约系统(eSign)

01 北京舒曼德医药科技开发有限公司:医药科技的数字化先锋 北京舒曼德医药科技开发有限公司(以下简称“舒曼德医药”)作为国内医药科技领域的领军企业,致力于创新药物的研发、临床试验和市场推广。公司以“科技兴药、质量为先、服…

【UE5】RTS游戏的框选功能+行军线效果实现

目录 效果 步骤 一、项目准备 二、框选NPC并移动到指定地点 三、框选效果 效果 步骤 一、项目准备 1. 新建一个俯视角游戏工程 2. 新建一个pawn、玩家控制器和游戏模式,这里分别命名为“MyPawn”、“MyController”和“MyGameMode” 3. 打开“MyGameMode”,设置玩家…

vim定位有问题的脚本/插件的一般方法

在使用vim的过程中可能会遇到一些报错或其他不符合预期的情况,本文介绍一些我自己常用的定位有问题脚本/插件的方法(以下方法同样适用于neovim) 执行了某些命令的情况 这种情况最简单,使用:h 命令,如果插件有文档的话…

智能驱动教育变革:人工智能在高中教育中的实践路径与创新策略

一、引言 随着信息技术的飞速发展,人工智能(Artificial Intelligence, AI)已成为推动社会进步的重要力量。在教育领域,人工智能的应用正逐渐改变着传统的教学模式和方法,为教育现代化注入了新的活力。高中教育作为教育…

VLAN(虚拟局域网)

一、vlan概述 VLAN(virtual local area network)是一种通过逻辑方式划分网络的技术,允许将一个物理网络划分为多个独立的虚拟网络。每一个vlan是一个广播域,不同vlan之间的通信需要通过路由器或三层交换机 [!注意] vlan是交换机独有的技术,P…

spring-cloud-starter-alibaba-seata使用说明

Spring Cloud Alibaba Seata 使用说明 spring-cloud-starter-alibaba-seata 是 Spring Cloud Alibaba 生态中用于集成分布式事务框架 Seata 的核心组件,支持 AT(自动补偿)、TCC(手动补偿) 等模式。 一、依赖配置 添加…

每日一题(小白)暴力娱乐篇23

由题意得知给我们一串数字,我们每次交换两位,最少交换多少次成功得到有顺序的数组。我们以平常的思维去思考,加入给你一串数字获得最少的交换次数,意味着你的交换后续基本不会变,比如说2 1 3 5 4 中1与2交换后不变&…

Python基础——Pandas库

对象的创建 导入 Pandas 时,通常给其一个别名“pd”,即 import pandas as pd。作为标签库,Pandas 对象在 NumPy 数组基础上给予其行列标签。可以说,列表之于字典,就如 NumPy 之于 Pandas。Pandas 中,所有数…

Spring入门概念 以及入门案例

Spring入门案例 Springspring是什么spring的狭义与广义spring的两个核心模块IoCAOP Spring framework特点spring入门案例不用new方法,如何使用返回创建的对象 容器:IoC控制反转依赖注入 Spring spring是什么 spring是一款主流的Java EE轻量级开源框架 …

The packaging for this project did not assign a file to the build artifact

问题: maven install报错:The packaging for this project did not assign a file to the build artifact 解决方案: 方案1: 使用mvn clean install 就可以解决问题, 方案2: 找到lifecycle点clean再点…

C++入门一:C++ 编程概述

一、C 语言与 C 的关系:从 “带类的 C” 到独立王国 1.1 血缘关系:C 是 C 的 “超级进化版” 起源:C 由 Bjarne Stroustrup 在 1980 年代开发,最初名为 “C with Classes”(带类的 C),旨在为 …

LLM生成文本的 束搜索参数是什么(Beam Search)

LLM生成文本的 束搜索参数是什么(Beam Search) 束搜索(Beam Search)是一种在序列生成任务(如机器翻译、文本生成等)中常用的启发式搜索算法,用于在搜索空间中寻找最优的生成序列。 束搜索的基本概念 在序列生成过程中,每一步都会有多个可能的选择(即候选标记)。 …

Java-多级排序结合thenComparing()

List<User>,user有个字段有值的时候设置1,没值就是null,怎么排序根据这个字段排序? 若要对 List<User> 按照某个字段(如 flag,有值时为 1,无值时为 null)排序,可 以使用 ​​Comparator​​ 结合 null 值处理逻辑。 1. 排序规则说明​​ 假设需求是:…

卷积神经网络(CNN)基础

目录 一、应用场景 二、卷积神经网络的结构 1. 输入层&#xff08;Input Layer&#xff09; 2. 卷积层&#xff08;Convolutional Layer&#xff09; 3. 池化层&#xff08;Pooling Layer&#xff09; 最大池化&#xff08;max_pooling&#xff09;或平均池化&#xff08;…

Android 中集成 Unity 工程的步骤

在 Adroid 项目中集成 Unity 工程,主要步骤如下: 一、前提条件 1、已有一个 Android 工程项目; 2、Unity 工程已导出为 Android 工程,目录大概如下: 二、集成步骤 1、在 Android 工程中导入 Unity 工程的 unityLibrary 模块。 在 Android Studio 中,点击菜单栏 Fil…

热Key问题及其解决方案:Redis高并发场景下的性能优化

目录 一、热Key问题的本质与影响 1.1 什么是热Key&#xff1f; 典型热Key场景&#xff1a; 1.2 热Key造成的技术挑战与业务影响 技术层面影响&#xff1a; 业务层面影响&#xff1a; 二、热Key的科学判定与识别方法 2.1 定量判定标准 QPS集中度指标 资源消耗指标 2.…