设计模式-模板模式

设计模式专栏

    • 模式介绍
    • 模式特点
    • 应用场景
    • 模板模式和工厂模式区别
    • 代码示例
      • Java实现模板模式
      • python实现模板模式
    • 模板模式在spring中的应用


模式介绍

模板模式是一种行为型设计模式,它通过将算法的骨架抽象成一个模板方法,将具体的操作留给子类来实现。这种模式的主要思想是将一个行为定义为一个框架,然后由子类填充细节。

在模板模式中,抽象类公开定义了执行它的方法的方式/模板。子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种模式旨在定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。

模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。模板模式封装不变部分,扩展可变部分,提取公共代码,便于维护。同时,行为由父类控制,子类实现。

然而,模板模式也有一些缺点。每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

模板模式适用于有多个子类共有的方法且逻辑相同的情况,对于重要的、复杂的方法,可以考虑作为模板方法。

在这里插入图片描述

模式特点

模板模式的优点主要包括:

  1. 提高代码复用性 :通过将相同处理逻辑的代码放到抽象类中,可以避免在多个子类中重复编写相同的代码,提高代码的复用性。
  2. 提高代码扩展性 :将不同的代码在不同的子类中实现,通过对子类的扩展增加新的行为,使得代码更加灵活,易于扩展。
  3. 符合开闭原则 :通过将不变的行为写在父类上,去除子类的重复代码,提供了一个很好的代码复用平台,符合开闭原则。

模板模式的缺点主要包括:

  1. 类数目的增加 :每一个抽象类都需要至少一个子类来实现,这样导致类的个数增加,从而导致系统复杂度的增加。
  2. 继承关系的缺点 :如果父类添加了新的抽象方法,所有子类都要增加该方法,这在一定程度上增加了代码的复杂性和维护成本。

模板模式在一定程度上可以提高代码的复用性和扩展性,但同时也增加了系统的复杂度。因此,在使用模板模式时需要谨慎考虑其优缺点。

在这里插入图片描述

应用场景

模板模式的应用场景主要包括以下几个方面:

  1. 算法骨架:当需要实现一个算法的不变部分,并将可变的行为留给子类来实现时,可以使用模板模式。例如,在排序算法中,比较大小的逻辑是固定的,但具体的排序方法(如冒泡排序、选择排序等)可以由子类来实现。

  2. 公共行为提取:当多个子类中拥有相同的方法,而且逻辑相同时,可以将这些方法抽出来放到一个模板抽象类中。这样可以避免代码重复,提高代码的可维护性和可扩展性。

  3. 主框架相同:当程序主框架相同,细节不同的情况下,也可以使用模板方法。例如,在Web开发中,前后端交互的流程通常是固定的,但具体的业务逻辑可以根据不同的需求来实现。

模板模式适用于那些需要定义一个算法骨架,将一些步骤留给子类来实现的场景。通过提取公共行为和避免代码重复,可以提高代码的可维护性和可扩展性。

在这里插入图片描述

模板模式和工厂模式区别

模板模式和工厂模式是两种不同的设计模式,它们在以下几个方面存在区别:

  1. 目的不同:模板模式的主要目的是通过定义一个抽象类,将一些公共的行为封装在抽象类中,然后通过继承抽象类来实现具体的业务逻辑。而工厂模式的主要目的是通过创建工厂类来管理对象的创建过程,从而降低代码的耦合度。

  2. 适用场景不同:模板模式适用于当系统中存在大量相似的对象,并且这些对象具有公共的行为和属性时。而工厂模式适用于当系统中存在大量相似的对象,并且这些对象的创建过程比较复杂时。

  3. 实现方式不同:模板模式通过继承抽象类来实现具体的业务逻辑,而工厂模式通过创建工厂类来管理对象的创建过程。

  4. 代码结构不同:模板模式的代码结构比较清晰,易于理解和维护。而工厂模式的代码结构相对较为复杂,需要仔细考虑工厂类的设计以及如何管理对象的创建过程。

模板模式和工厂模式在目的、适用场景、实现方式和代码结构等方面存在区别。在使用时需要根据具体的需求和场景来选择合适的设计模式。

在这里插入图片描述

代码示例

Java实现模板模式

以下是Java实现模板模式的示例代码:

// 抽象类,定义模板方法
public abstract class AbstractClass {public void templateMethod() {doSomething();doSomethingElse();}// 具体方法,由子类实现public abstract void doSomething();// 具体方法,由子类实现public abstract void doSomethingElse();
}// 具体子类1,实现抽象类中的方法
public class ConcreteClass1 extends AbstractClass {@Overridepublic void doSomething() {System.out.println("ConcreteClass1 do something");}@Overridepublic void doSomethingElse() {System.out.println("ConcreteClass1 do something else");}
}// 具体子类2,实现抽象类中的方法
public class ConcreteClass2 extends AbstractClass {@Overridepublic void doSomething() {System.out.println("ConcreteClass2 do something");}@Overridepublic void doSomethingElse() {System.out.println("ConcreteClass2 do something else");}
}// 客户端代码,使用模板模式
public class Client {public static void main(String[] args) {AbstractClass abstractClass1 = new ConcreteClass1();abstractClass1.templateMethod(); // 输出:ConcreteClass1 do something\nConcreteClass1 do something else\nAbstractClass abstractClass2 = new ConcreteClass2();abstractClass2.templateMethod(); // 输出:ConcreteClass2 do something\nConcreteClass2 do something else\n}
}

在上面的示例代码中,我们定义了一个抽象类AbstractClass,其中定义了一个模板方法templateMethod(),和两个抽象方法doSomething()doSomethingElse()。然后,我们定义了两个具体子类ConcreteClass1ConcreteClass2,分别实现了抽象类中的方法。最后,在客户端代码中,我们创建了两个具体子类的实例,并调用了它们的模板方法。通过运行程序,我们可以看到,不同的具体子类实现了不同的逻辑,但它们的调用方式是一样的。这就是模板模式的优点之一,它可以将公共的行为封装在抽象类中,从而避免代码的重复和冗余。

python实现模板模式

以下是Python实现模板模式的示例代码:

from abc import ABC, abstractmethod# 抽象类,定义模板方法
class AbstractClass(ABC):@abstractmethoddef primitive_operation1(self):pass@abstractmethoddef primitive_operation2(self):passdef template_method(self):self.primitive_operation1()self.primitive_operation2()# 具体子类1,实现抽象类中的方法
class ConcreteClass1(AbstractClass):def primitive_operation1(self):print("ConcreteClass1 primitive_operation1")def primitive_operation2(self):print("ConcreteClass1 primitive_operation2")# 具体子类2,实现抽象类中的方法
class ConcreteClass2(AbstractClass):def primitive_operation1(self):print("ConcreteClass2 primitive_operation1")def primitive_operation2(self):print("ConcreteClass2 primitive_operation2")# 客户端代码,使用模板模式
if __name__ == '__main__':concrete_class1 = ConcreteClass1()concrete_class1.template_method()  # 输出:ConcreteClass1 primitive_operation1\nConcreteClass1 primitive_operation2\nconcrete_class2 = ConcreteClass2()concrete_class2.template_method()  # 输出:ConcreteClass2 primitive_operation1\nConcreteClass2 primitive_operation2\n

在这个示例中,我们使用了Python的内置abc模块来定义抽象类和抽象方法。在抽象类AbstractClass中,我们定义了一个模板方法template_method(),并在其中调用了两个抽象方法primitive_operation1()primitive_operation2()。然后,我们定义了两个具体子类ConcreteClass1ConcreteClass2,分别实现了抽象类中的方法。最后,在客户端代码中,我们创建了两个具体子类的实例,并调用了它们的模板方法。通过运行程序,我们可以看到,不同的具体子类实现了不同的逻辑,但它们的调用方式是一样的。这就是模板模式的优点之一,它可以将公共的行为封装在抽象类中,从而避免代码的重复和冗余。

在这里插入图片描述

模板模式在spring中的应用

在Spring框架中,模板模式被广泛应用,以简化常见任务的执行,并提供一种可扩展的方式来处理特定场景下的重复代码。以下是模板模式在Spring中的几个应用示例:

  1. JdbcTemplate :Spring框架中的JdbcTemplate类是使用模板模式的一个典型示例。它封装了常规的数据库访问流程,如连接管理、异常处理等,并提供了简化的方法来执行SQL查询和更新操作。开发人员只需提供SQL语句和必要的参数,而无需关心底层的数据库访问细节。
  2. HibernateTemplate :对于使用Hibernate作为ORM工具的应用程序,Spring提供了HibernateTemplate类。该类封装了Hibernate会话的管理和常见操作,使开发人员能够更方便地执行数据库访问操作,如保存、查询和删除实体对象。
  3. JmsTemplate :对于使用Java消息服务(JMS)的应用程序,Spring提供了JmsTemplate类。该类简化了JMS消息的生产和消费过程,隐藏了底层的JMS API调用和资源管理。开发人员可以使用JmsTemplate发送和接收消息,而无需编写繁琐的JMS代码。
  4. RestTemplate :在Spring中,RestTemplate是用于执行HTTP请求的类。它提供了一种简单的方式来调用RESTful Web服务,封装了HTTP请求的创建、发送和处理过程。开发人员可以使用RestTemplate发送GET、POST、PUT、DELETE等请求,并处理响应结果。

这些模板类在Spring中提供了一致的使用方式和类似的方法签名,使得开发人员能够轻松地执行常见的任务,而无需编写大量的重复代码。同时,它们也提供了扩展点,允许开发人员根据需要进行自定义操作。通过使用这些模板类,开发人员可以更加专注于业务逻辑的实现,而不是底层技术细节的处理。

在这里插入图片描述

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

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

相关文章

iPhone 与三星手机:哪一款最好?

三星比苹果好吗?还是苹果比三星更好? 小米公司如何称霸全球智能手机市场?小米公司,由雷军创立于2010年,是一家领先的电子巨头。以其MIUI系统和互联网服务闻名,小米公司在全球智能手机市场中稳居前列。小米…

网络(七)路由协议以及相关配置

目录 一、路由器的工作原理 二、路由表的形成 2.1 直连网段 2.2 非直连网 2.3 路由表解析 2.3.1 查看路由表 2.3.2 解析 三、静态路由和默认路由 1. 静态路由 1.1 定义 1.2 特点 2. 默认路由 2.1 定义 2.2 特点 四、静态路由和默认路由的配置 1. 静态路由配置…

flutter学习-day12-可滚动组件和监听

📚 目录 简介可滚动组件 SingleChildScrollViewListView separated分割线无限加载列表带标题列表 滚动监听和控制 ScrollController滚动监听NotificationListener滚动监听 AnimatedList动画列表滚动网格布局GridView 横轴子元素为固定数量横轴子元素为固定最大长度…

[wp]第四届江西省赣网杯网络安全大赛-web 部分wp

第四届江西省赣网杯网络安全大赛(gwb)线上预选赛 因为学业繁忙 只玩了1小时,后续看看补一下这些 2023gwb-web1 九宫格拼图 2023gwb-web2 $filexxx;extract($_GET);if(isset($fun)){$contenttrim(file_get_contents($file));if($fun!&…

MLX:苹果 专为统一内存架构(UMA) 设计的机器学习框架

“晨兴理荒秽,带月荷锄归” 夜深闻讯,有点兴奋~ 苹果为 UMA 设计的深度学习框架真的来了 统一内存架构 得益于 CPU 与 GPU 内存的共享,同时与 MacOS 和 M 芯片 交相辉映,在效率上,实现对其他框架的降维打…

uniapp之屏幕右侧出现滚动条去掉、隐藏、删除【好用!】

目录 问题解决大佬地址最后 问题 解决 在最外层view上加上class“content”;输入以下样式。注意:两个都必须存在在生效。 .content {/* 跟屏幕高度一样高,不管view中有没有内容,都撑开屏幕高的高度 */height: 100vh; overflow: auto; } .content::-webkit-scrollb…

【JavaWeb】往浏览器打印一个hello world

上集:建一个web项目 第一步:建好Servlet类的文件 右键src,建一个class 就行 第二步:编代码 可以直接复制粘贴 用来测试的类 import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; //↓是注解&#xff0…

Java 基础学习(十一)File类与I/O操作

1 File类 1.1 File类概述 1.1.1 什么是File类 File是java.io包下作为文件和目录的类。File类定义了一些与平台无关的方法来操作文件,通过调用File类中的方法可以得到文件和目录的描述信息,包括名称、所在路径、读写性和长度等,还可以对文件…

Graphics Profiler 使用教程

GraphicsProfiler 使用教程 1.工具简介:2.Navigation介绍2.1.打开安装好的Graphics Profiler。2.2.将手机连接到计算机,软件会在手机中安装一个GraphicsProfiler应用(该应用是无界面的)。2.3.Show files list2.4.Record new trace2.4.1.Appli…

听GPT 讲Rust源代码--src/tools(13)

File: rust/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs 在Rust源代码中,路径为rust/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs的文件是为了处理Rust代码中的不一致实现问题而存在的。…

Linux 动态库和静态库

文章目录 前言动态库创建和使用静态库创建和使用动态库和静态库差异生成过程的差异运行效果的差异 补充说明库的名称的注意事项库的搜索路径的方法什么是位置无关代码动态链接与静态链接/usr/lib 和 /usr/local/lib 前言 动静态库的创建和使用部分更多的是意在说明动态库和静态…

关于枚举的简单理解

1. 枚举的简单认识 1.1 枚举的引入 枚举是在JDK1.5以后引入的。主要用途是:将一组常量组织起来,在这之前表示一组常量通常使用定义常量的方式如下面的代码所示: public static final int RED 1; public static final int GREEN 2; public…

【MySQL】(DDL)总结

总结: 1.DDL数据库操作 show database; //查看当前创建的数据库 create database 数据库名; //创建数据库 use 数据库; //切换数据库 select database(); //查看当前所处的数据库(当前进入的那个数据库) drop database 数据库名; //删除数据库名 2.DDL表操作 …

鸿蒙开发之网络请求

//需要导入http头文件 import http from ohos.net.http//请求地址url: string http://apis.juhe.cn/simpleWeather/queryText(this.message).maxFontSize(50).minFontSize(10).fontWeight(FontWeight.Bold).onClick(() > {console.log(请求开始)let req http.createHttp()…

【音视频 | H.264】H.264视频编码及NALU详解

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…

2023“楚怡杯”湖南省赛“信息安全管理与评估“--数字取证调查(高职组)

2023“楚怡杯”湖南省“信息安全管理与评估”(高职组)任务书 2023“楚怡杯”湖南省“信息安全管理与评估”(高职组)任务书第一阶段竞赛项目试题第二阶段竞赛项目试题第二部分 数字取证调查:需要环境私聊博主:2023“楚怡杯”湖南省“信息安全管理与评估”(高职组)任务书…

C语言——谁考了第k名(头歌编程刷题)

目录 一、题目描述: 二、输入格式: 三、输出格式: 四、输出样例: 五、输出样例: 六、代码呈现: 一、题目描述: 在一次考试中,每个学生的成绩都不相同,现知道了每个…

TCP与UDP:网络世界中的“顺丰快递”与“广播电台”

随着互联网的普及,我们每天都在与网络打交道。而在这背后,数据的传输离不开TCP和UDP这两种传输协议。它们就像网络世界中的“顺丰快递”和“广播电台”,各自有着不同的工作方式和特点。让我们一起来了解一下它们吧! 一、TCP&…

如何下载 GitHub 私有仓库

概述 GitHub 是一个用于托管代码的开源平台。它提供私有仓库功能,允许用户将代码保密。如果您需要下载 GitHub 私有仓库,可以使用以下两种方式。 方式一:使用 SSH 密钥 SSH 密钥是一种安全的身份验证方法,可用于访问 GitHub 私…

了解 Flutter 3.16 功能更新

作者 / Kevin Chisholm 我们在季度 Flutter 稳定版发布会上带来了 Flutter 3.16,此版本包含诸多更新: Material 3 成为新的默认主题、为 Android 带来 Impeller 的预览版、允许添加适用于 DevTools 的扩展程序等等,以及同步推出 Flutter 休闲游戏工具包重…