java设计模式学习之【模板方法模式】

news2024/10/5 17:51:07

文章目录

  • 引言
  • 模板方法模式简介
    • 定义与用途
    • 实现方式
  • 使用场景
  • 优势与劣势
  • 在Spring框架中的应用
  • 游戏设计示例
  • 代码地址

引言

设想你正在准备一顿晚餐,无论你想做意大利面、披萨还是沙拉,制作过程中都有一些共同的步骤:准备原料、加工食物、摆盘。这里,整个烹饪流程就像一个模板,而具体的菜肴则在这个模板的基础上添加了特有的步骤。在软件开发中,我们经常遇到类似的情况,某些过程的结构相同,但某些步骤的具体实现不同。模板方法模式正是用于解决这类问题的一种设计模式,它在定义算法骨架的同时,将一些步骤的实现延迟到子类。

模板方法模式简介

定义与用途

模板方法模式(Template Method Pattern)是一种行为型设计模式,它在父类中定义了一个操作的算法骨架,而将一些步骤的具体实现延迟到子类中。通过这种方式,可以重新定义算法的某些步骤而不改变算法的结构。

实现方式

实现模板方法模式通常涉及以下几个关键组件:

  • 抽象类(Abstract Class):定义了模板方法和算法的骨架。模板方法设置为 final,这样它就不能被重写。它调用一系列的操作,其中一些操作由子类实现。
  • 具体类(Concrete Class):实现抽象类中的抽象方法,定义了算法中与特定主题相关的步骤。

使用场景

模板方法模式适用于以下场景:

  • 当有多个算法具有相同的算法结构,但算法的某些步骤在不同的情况下有不同的实现时。
  • 当需要控制子类扩展的点时,可以在一些操作中定义钩子(hook)。

例如:

  • 数据解析框架: 定义一个解析数据的模板方法,具体的解析步骤如读取数据、分析数据和处理数据可以在子类中实现。
  • 软件构建过程: 软件构建工具可以定义一系列构建步骤的模板,如清理、编译、测试和打包,具体的步骤根据不同的项目而定制。
  • 游戏设计: 游戏可以定义一个游戏流程模板,如开始游戏、进行游戏和结束游戏,具体的游戏逻辑在不同的游戏子类中实现。

优势与劣势

  • 优势
    • 提供了代码复用的平台,通过模板方法,公共代码移动到单一位置,减少代码冗余。
    • 提供了一种扩展部分算法的方法,子类可以在不改变算法结构的情况下重新定义算法的某些特定步骤。
  • 劣势
    • 对于每个不同的实现,都需要一个新的子类,可能会导致系统中类的数量增加。
    • 有时候可能违背了里氏替换原则,因为子类改变了父类的预期行为。

在Spring框架中的应用

1. JdbcTemplate
JdbcTemplate 是Spring提供的一个优秀的数据库操作工具,它实现了模板方法模式。Spring定义了一个抽象的 JdbcOperations 接口,提供了执行数据库操作的模板方法。JdbcTemplate 类实现了这些方法,管理数据库连接、声明语句的创建和执行、结果集的遍历处理等。用户只需要提供SQL语句和定义如何映射结果集到对象,其他的数据库操作细节(如异常处理、事务管理等)都由模板方法处理。

2. TransactionTemplate
Spring的 TransactionTemplate 也是模板方法模式的一个应用实例。它提供了一个模板,用于执行带有事务管理的代码块。用户只需要提供需要在事务环境中执行的代码,而事务的管理(开始、提交、回滚等)则是在模板内部处理的。这使得用户不需要直接与底层的事务API打交道,简化了事务管理的代码。

3. Spring Web MVC
在Spring Web MVC框架中,DispatcherServlet 提供了一个模板方法来处理HTTP请求。它定义了处理请求的整体流程:解析请求、寻找对应的处理器、渲染视图等。在这个流程中,可以插入各种预处理器、后处理器和视图解析器来定制请求处理的行为。开发者通过扩展特定的方法,提供自己的处理逻辑。

4. Spring Security
Spring Security中的过滤器链也是一个模板方法模式的实例。它定义了一系列的安全检查过程,每一个过滤器都是一个检查的实现。开发者可以通过添加或移除过滤器,或者自定义过滤器来定制安全检查的流程。

游戏设计示例

在这里插入图片描述
步骤 1:创建一个带有模板方法的抽象类

public abstract class Game {
   abstract void initialize();
   abstract void startPlay();
   abstract void endPlay();

   // 模板方法
   public final void play(){

      // 初始化游戏
      initialize();

      // 开始游戏
      startPlay();

      // 结束游戏
      endPlay();
   }
}

Game 是一个抽象类,定义了三个抽象方法:initialize、startPlay 和 endPlay,用于子类实现具体的游戏初始化、开始和结束的行为。它还定义了一个模板方法 play,该方法按顺序调用这三个方法,设置为 final 以防止子类覆盖。

步骤 2:创建扩展上述类的具体类

public class Cricket extends Game {

   @Override
   void endPlay() {
      System.out.println("板球游戏结束了!");
   }

   @Override
   void initialize() {
      System.out.println("板球游戏初始化了!开始玩吧。");
   }

   @Override
   void startPlay() {
      System.out.println("板球游戏开始了。享受游戏!");
   }
}

Cricket 是 Game 的一个具体子类,它实现了板球游戏的具体行为。

public class Football extends Game {

   @Override
   void endPlay() {
      System.out.println("足球游戏结束了!");
   }

   @Override
   void initialize() {
      System.out.println("足球游戏初始化了!开始玩吧。");
   }

   @Override
   void startPlay() {
      System.out.println("足球游戏开始了。享受游戏!");
   }
}

Football 是另一个具体的 Game 子类,实现了足球游戏的具体行为。

步骤 3:使用游戏的模板方法 play() 来演示游戏的定义方式

public class TemplatePatternDemo {
   public static void main(String[] args) {

      Game game = new Cricket();
      game.play();
      System.out.println();
      game = new Football();
      game.play();      
   }
}

在这里插入图片描述

在这个演示类中,先创建了一个 Cricket 对象,并调用其 play 方法来执行整个板球游戏流程。然后,创建了一个 Football 对象,并再次调用 play 方法来执行足球游戏流程。

这个示例演示了模板方法模式如何定义算法的骨架,同时将一些步骤的具体实现延迟到子类中。通过这种方式,Cricket 和 Football 可以有自己独特的游戏流程,同时共享游戏流程的结构。这使得算法的结构定义一次,可以被多次复用,而且更容易进行扩展。

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

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

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

相关文章

你知道继电保护测试仪的价格是多少吗?

继电保护测试仪是电气设备检测中经常使用的检测仪器。它能准确、快速地检测到每个继电保护装置的一些潜在故障和问题,帮助电力检测工人锁定问题点,使继电保护装置能够正常工作,保护电力需求。继电保护测试仪贵吗?哪些因素影响价格…

Hive讲课笔记:内部表与外部表

文章目录 一、导言二、内部表1.1 什么是内部表1.1.1 内部表的定义1.1.2 内部表的关键特性 1.2 创建与操作内部表1.2.1 创建并查看数据库1.2.2 在park数据库里创建student表1.2.3 在student表插入一条记录1.2.4 通过HDFS WebUI查看数据库与表 三、外部表2.1 什么是外部表2.2 创建…

优思学院|做了3年QC感到前路茫茫,我应该如何规划职业路径?

网友提问: 做了3年QC感到前路茫茫我应该如何规划职业路径? 在当今这个快速发展和竞争激烈的时代,许多质量控制(QC)领域的专业人士,如你所述,可能会感到职业发展上的迷茫。 作为一名拥有三年QC经…

JavaWeb——JQuery

文章目录 JQuery 是什么?jQuery 的原理示意图JQuery 基本开发步骤jQuery 对象和 DOM 对象将dom对象转为JQuery对象jQuery 对象转成 DOM 对象jQuery 选择器基本选择器基础过滤选择器JQuery 是什么? 基本介绍 jQuery 是一个快速的,简洁的 javaScript 库,使用户能更方便地处理…

elasticsearch系列七:聚合查询

概述 今天咱们来看下es中的聚合查询,在es中聚合查询分为三大类bucket、metrics、pipeline,每一大类下又有十几种小类,咱们各举例集中,有兴许的同学可以参考官网:https://www.elastic.co/guide/en/elasticsearch/refere…

ClickHouse基础知识(五):ClickHouse的SQL 操作

基本上来说传统关系型数据库(以 MySQL 为例)的 SQL 语句,ClickHouse 基本都支持, 这里不会从头讲解 SQL 语法只介绍 ClickHouse 与标准 SQL(MySQL)不一致的地方。 1. Insert 基本与标准 SQL(My…

【Vue2+3入门到实战】(13)插槽<slot>详细示例及自定义组件的创建与使用代码示例 详解

目录 一、学习目标1.插槽2.综合案例:商品列表 一、插槽-默认插槽1.作用2.需求3.问题4.插槽的基本语法5.代码示例6.总结 二、插槽-后备内容(默认值)1.问题2.插槽的后备内容3.语法4.效果5.代码示例 三、插槽-具名插槽1.需求2.具名插槽语法3.v-s…

BDD - Python Behave 配置文件 behave.ini

BDD - Python Behave 配置文件 behave.ini 引言behave.ini配置参数的类型配置项 behave.ini 应用feature 文件step 文件创建 behave.ini执行 Behave查看配置默认值 behave -v 引言 前面文章 《BDD - Python Behave Runner Script》就是为了每次执行 Behave 时不用手动敲一长串…

node 项目中 __dirname / __filename 是什么,为什么有时候不能用?

__dirname 是 Node.js 中的一个特殊变量,表示当前执行脚本所在的目录的绝对路径。 __filename 同理,是 Node.js 中的一个特殊变量,表示当前执行脚本的绝对路径,包括文件名。 在 Node.js 中,__dirname / __filename是…

C语言 linux文件操作(二)

文章目录 一、获取文件长度二、追加写入三、覆盖写入四、文件创建函数creat 一、获取文件长度 通过lseek函数,除了操作定位文件指针,还可以获取到文件大小,注意这里是文件大小,单位是字节。例如在file1文件中事先写入"你好世…

Vue - v-for 指令详解

1. 渲染列表 首先&#xff0c;让我们看看如何使用 v-for 渲染一个简单的列表。在 Vue.js 中&#xff0c;我们可以使用 v-for 来遍历数组&#xff0c;并根据数组中的每个元素渲染相应的内容。 <template><div><!-- 使用 v-for 渲染列表 --><ul><li…

计算机与人工智能:共创智能时代的新篇章

计算机与人工智能&#xff1a;共创智能时代的新篇章 在这个科技日新月异的时代&#xff0c;计算机与人工智能&#xff08;AI&#xff09;的结合正以前所未有的速度改变着世界。它们在各自的领域内飞速发展&#xff0c;而当这两者相遇时&#xff0c;它们产生了巨大的能量&#x…

ClickHouse基础知识(六):ClickHouse的副本配置

副本的目的主要是保障数据的高可用性&#xff0c;即使一台 ClickHouse 节点宕机&#xff0c;那么也可以 从其他服务器获得相同的数据。 1. 副本写入流程 2. 配置步骤 ➢ 启动 zookeeper 集群 ➢ 在hadoop101的/etc/clickhouse-server/config.d目录下创建一个名为metrika.xml…

can通信的验收码和屏蔽码怎么计算

方法一&#xff1a;直接用canTest软件并按下图计算&#xff08;借助工具&#xff0c;比较方便&#xff09; 方法二&#xff1a;明白规则

探索Apache Commons Imaging处理图像

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;咱们今天来聊聊图像处理。在这个数字化日益增长的时代&#xff0c;图像处理已经成为了一个不可或缺的技能。不论是社交媒体上的照片编辑&#xff0c;还是专业领域的图像分析&#xff0c;图像处理无处不在。而作为…

RAD Studio 12 安装激活说明及常见问题

目录 RAD Studio 安装说明 RAD Studio 最新的修补程序更新 RAD Studio 产品相关信息 Embarcadero 产品在线注册步骤 单机版授权产品注册注意事项 Embarcadero 产品离线注册步骤 Embarcadero 产品安装次数查询 Embarcadero 序号注册次数限制 EDN账号 - 查询授权序号、下…

idea 插件开发之 HelloWorld

前言 本文使用的 idea 2023.3 版本进行插件入门开发&#xff0c;首先要说明的是 idea 2023 版本及以后的 idea&#xff0c;对插件开发进行了一定程度的变动&#xff1a; 1、创建项目时不再支持 maven 选项 2、必须是 jdk17 及以后版本&#xff08;点击查看官网版本对应关系&…

react 之 美团案例

1.案例展示 2.环境搭建 克隆项目到本地&#xff08;内置了基础静态组件和模版&#xff09; git clone http://git.itcast.cn/heimaqianduan/redux-meituan.git 安装所有依赖 npm i 启动mock服务&#xff08;内置了json-server&#xff09; npm run serve 启动前端服务 npm…

苹果手机打开Microsoft Outlook日历ics文件方法

作为一名经常需要处理各种日程安排的苹果用户&#xff0c;我深知ics文件的重要性。ics文件通常来自于我们日常使用的日历应用&#xff0c;比如Microsoft Outlook&#xff0c;是日程信息的标准格式。但很多时候&#xff0c;当我们尝试打开这些ics文件时&#xff0c;却会遇到种种…

re:Invent 2023技术上新|Amazon DynamoDB与OpenSearch Service的Zero-ETL集成

Amazon DynamoDB 与 Amazon OpenSearch Service 的 Zero-ETL 集成已正式上线&#xff0c;该服务允许您通过自动复制和转换您的 DynamoDB 数据来搜索数据&#xff0c;而无需自定义代码或基础设施。这种 Zero-ETL 集成减少了运营负担和成本&#xff0c;使您能够专注于应用程序。这…