当前位置: 首页 > news >正文

GPT带我学-设计模式-模板模式

1 请你给我介绍一下设计模式中的模板模式

模板模式是一种行为设计模式,它定义了一个算法的骨架,将一些步骤的具体实现延迟到子类中。模板模式允许子类重新定义算法的某些特定步骤,而不需要改变算法的结构。

模板模式由以下几个角色组成:

  • 抽象类(Abstract Class):抽象类定义了一个模板方法,该方法定义了算法的骨架,包含了一系列抽象方法或可选的具体实现方法。抽象类可以提供默认的实现,也可以作为模板方法的一部分使用。
  • 具体类(Concrete Class):具体类实现了抽象类中定义的抽象方法,完成了算法中的具体步骤。

模板模式的工作流程如下:

  1. 定义一个抽象类,其中包含一个模板方法。
  2. 在模板方法中定义算法的骨架,即一系列的步骤。
  3. 将某些具体步骤的实现延迟到子类中,通过定义抽象方法或可选的具体实现方法来实现。
  4. 具体子类继承抽象类,并实现其中的抽象方法或可选的具体实现方法,完成算法中的具体步骤。
  5. 客户端通过调用抽象类的模板方法来使用模板模式。

模板模式的优点包括:

  1. 通过定义算法的骨架,使算法的结构更加清晰明了。
  2. 提供了一种方便的扩展算法的方式。只需继承抽象类并实现相应的方法即可。
  3. 将公共的代码抽取到父类中,避免了代码的重复。

模板模式的缺点包括:

  1. 可能会导致类的数量增加:因为模板模式需要定义抽象类和具体类,所以可能会导致类的数量增加,特别是当有多个变种的算法时。
  2. 可能会引入不必要的复杂性:模板模式将算法的具体实现分散到不同的类中,可能会增加代码的复杂性和理解难度。
  3. 不太灵活:因为模板模式的算法骨架是固定的,所以对于需要大量变动的算法,模板模式可能不太适用。如果有太多的不同步骤和变种,维护和使用模板模式可能会变得困难。
  4. 可能会限制了代码的扩展性:因为算法的结构是固定的,所以对于需要频繁变动的部分,可能需要修改抽象类的结构,这可能会影响到其他使用该模板的类。

总结来说,模板模式通过定义算法的骨架和将具体步骤的实现延迟到子类中,提供了一种方便的算法设计和扩展方式,可以提高代码的重用性和可维护性。

2 请你用java举一个实际一点的例子

好的,下面是一个使用模板模式的java示例:
在下面的示例中,抽象类 Game 定义了一个模板方法 play(),它定义了一个游戏的骨架,包含了初始化游戏、开始游戏和结束游戏的步骤。具体的游戏类 Football 和 Basketball 继承抽象类 Game,并实现了抽象方法,在不同的具体类中完成了对应的具体步骤。

abstract class Game {abstract void initialize();abstract void startPlay();abstract void endPlay();// 模板方法public final void play() {// 初始化游戏initialize();// 开始游戏startPlay();// 结束游戏endPlay();}
}class Football extends Game {@Overridevoid initialize() {System.out.println("Football Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Football Game Started. Enjoy the game!");}@Overridevoid endPlay() {System.out.println("Football Game Finished!");}
}class Basketball extends Game {@Overridevoid initialize() {System.out.println("Basketball Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Basketball Game Started. Enjoy the game!");}@Overridevoid endPlay() {System.out.println("Basketball Game Finished!");}
}public class TemplatePatternExample {public static void main(String[] args) {Game footballGame = new Football();footballGame.play();System.out.println("------------------------------");Game basketballGame = new Basketball();basketballGame.play();}
}

通过创建不同的具体游戏对象,然后调用它们的 play() 方法,我们可以按照固定的游戏流程来玩足球游戏和篮球游戏。输出结果如下:

Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!
------------------------------
Basketball Game Initialized! Start playing.
Basketball Game Started. Enjoy the game!
Basketball Game Finished!

这个例子展示了模板模式的应用,通过定义抽象类的模板方法,将游戏的算法骨架固定下来,并将具体的步骤实现延迟给子类,从而实现了游戏的统一流程管理,同时也提供了扩展游戏的方式。

3 模板模式有几种形式

模板模式有两种常见的形式:

  • 基本的模板模式(Basic Template Pattern):基本的模板模式是指通过抽象类定义算法的骨架,将某些步骤的具体实现延迟到子类中。抽象类中的模板方法定义了算法的骨架,包含了一系列的抽象方法或具体实现方法。子类继承抽象类,并实现其中的抽象方法,完成算法中的具体步骤。

  • 钩子方法模式(Hook Method Pattern):钩子方法模式是基本的模板模式的扩展,它允许子类在父类的算法中插入或不插入一些特定的行为。钩子方法是指在抽象类中提供一个空实现或默认返回值的抽象方法,子类可以选择性地覆盖或使用这些钩子方法,按需插入自己的行为。

这两种形式都遵循了模板模式的基本原则,即通过抽象类定义算法的骨架,将某些具体步骤的实现延迟到子类中,以实现代码重用和扩展的目的。在实际应用中,根据需要选择合适的形式来设计和实现模板模式。

4 那请你用钩子方法模式修改上面游戏的代码

好的,以下是使用钩子方法模式修改上述游戏代码的示例:

abstract class Game {abstract void initialize();abstract void startPlay();abstract void endPlay();// 钩子方法,允许子类在父类的算法中插入特定行为protected boolean additionalPlay() {return true;}// 模板方法public final void play() {initialize();startPlay();// 在这里插入额外的行为if (additionalPlay()) {playExtra();}endPlay();}// 钩子方法protected void playExtra() {// 默认空实现}
}class Football extends Game {@Overridevoid initialize() {System.out.println("Football Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Football Game Started. Enjoy the game!");}@Overridevoid endPlay() {System.out.println("Football Game Finished!");}@Overrideprotected void playExtra() {System.out.println("Football Game: Play some extra time.");}
}class Basketball extends Game {@Overridevoid initialize() {System.out.println("Basketball Game Initialized! Start playing.");}@Overridevoid startPlay() {System.out.println("Basketball Game Started. Enjoy the game!");}@Overridevoid endPlay() {System.out.println("Basketball Game Finished!");}
}public class TemplatePatternExample {public static void main(String[] args) {Game footballGame = new Football();footballGame.play();System.out.println("------------------------------");Game basketballGame = new Basketball();basketballGame.play();}
}

在这个示例中,我们在抽象类 Game 中添加了一个钩子方法 additionalPlay() 和一个默认的钩子方法 playExtra()。在模板方法 play() 中,我们在适当的时机使用了钩子方法 additionalPlay() 来决定是否执行额外的行为。在 Football 类中,我们覆盖了默认的钩子方法 playExtra() 来执行一些额外的操作。

当运行这个示例时,输出结果如下

Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game: Play some extra time.
Football Game Finished!
------------------------------
Basketball Game Initialized! Start playing.
Basketball Game Started. Enjoy the game!
Basketball Game Finished!

可以看到,在具体游戏类 Football 中,在运行模板方法 play() 时,额外的钩子方法 playExtra() 被调用了。而在具体游戏类 Basketball 中,并没有对钩子方法进行覆盖,所以默认的行为为空。

通过使用钩子方法模式,我们可以在父类的算法中插入特定的行为,通过选择性地覆盖钩子方法,在子类中自定义额外的操作。这种方式增强了模板方法的灵活性和可扩展性。

5 通常用在什么场景

模板模式通常适用于以下场景:

算法的整体流程是固定的,但某些步骤的具体实现可能会有所不同。通过模板模式,可以将整体流程封装在一个模板方法中,将具体实现延迟到子类中。
多个类具有相似的行为,但实现细节不同。通过模板模式,可以将共同的行为抽象为父类,将不同的实现细节委托给子类。
需要一种代码复用和扩展方式,以避免代码的重复。通过提供模板方法和抽象方法,可以在不同的子类中实现具体细节,实现代码的重用和扩展。

一些常见的应用场景包括:

框架或库的设计:框架或库通常会定义一些通用的算法或流程,供用户来实现具体的细节。模板模式可以将通用的算法骨架封装在父类中,用户可以通过实现抽象方法来定制化具体实现。
数据库访问:数据库访问通常包含一些通用的操作流程,如连接数据库、执行SQL语句、处理结果等。模板模式可以将这些通用流程封装在父类中,具体的数据库操作细节委托给子类。
Web开发中的请求处理:在Web开发中,处理请求通常包含一些通用的步骤,如请求解析、数据验证、业务逻辑处理、结果响应等。模板模式可以将这些通用步骤封装在父类中,将具体的处理细节留给子类实现。

总之,模板模式适用于任何需要固定算法框架,并通过子类实现具体细节的情况。它可以提高代码的复用性和扩展性,并确保整体流程的一致性。

总结

模板模式是一种行为型的设计模式,所以就是对行为的控制。其实质就是用抽象方法固定了流程,每个流程的具体实现交给其子类实现。从而统一流程。

相关文章:

GPT带我学-设计模式-模板模式

1 请你给我介绍一下设计模式中的模板模式 模板模式是一种行为设计模式,它定义了一个算法的骨架,将一些步骤的具体实现延迟到子类中。模板模式允许子类重新定义算法的某些特定步骤,而不需要改变算法的结构。 模板模式由以下几个角色组成&…...

Windows下调试UEFI程序:Visual Studio调试

以edk2\MdeModulePkg\Application\HelloWorld这个项目作为调试目标。 1. 使用VS2017建立Makefile工程 VS2017, 新建 project,取名X64dbg_vs。 Visual C > Other > Makefile Project, 注意项目路径为HelloWord程序路径。 随便填写config中的字符串&#xff…...

Vue中监听路由参数变化的几种方式

目录 一. 路由监听方式: 通过 watch 进行监听 1. 监听路由从哪儿来到哪儿去 2. 监听路由变化获取新老路由信息 3. 监听路由变化触发方法 4. 监听路由的 path 变化 5. 监听路由的 path 变化, 使用handler函数 6. 监听路由的 path 变化,触发method…...

angular——子组件如何接收父组件的动态传值

开发过程中,父组件给子组件传值的情况很常见,今天我们就来聊聊父组件给子组件传值可能会发生哪些意外,什么情况下子组件无法接收到父组件最新的传值; 传值情况: 基本数据类型:父组件给子组件传递 基本数据…...

php 桥接模式

一,桥接模式,是结构设计模式的一种,其将抽象部分和实现部分分离开来,使两部分可以独立的进行修改,提高系统的灵活性。在桥接模式中,需要定义一个抽象类和一个实现类,通过将实现类注入到抽象类中…...

Android 13 Hotseat定制化修改——004 hotseat布局位置

目录 一.背景 二.原生hotseat布局位置 三.修改Hotseat布局位置 一.背景 由于需求是需要自定义修改Hotseat,所以此篇文章是记录如何自定义修改hotseat的,应该可以覆盖大部分场景,修改点有修改hotseat布局方向,hotseat图标数量,hotseat图标大小,hotseat布局位置,hotseat…...

海外版金融理财系统源码 国际投资理财系统源码 项目投资理财源码

海外版金融理财系统源码 国际投资理财系统源码 项目投资理财源码...

洛谷P1162 - 填涂颜色

题目描述 由数字 0 0 0 组成的方阵中,有一任意形状闭合圈,闭合圈由数字 1 1 1 构成,围圈时只走上下左右 4 4 4 个方向。现要求把闭合圈内的所有空间都填写成 2 2 2。例如: 6 6 6\times 6 66 的方阵( n 6 n6 n6&…...

设计模式十一:外观模式(Facade Pattern)

外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用于访问系统中的一组复杂子系统。外观模式通过将复杂子系统的接口封装在一个高层接口中,简化了客户端与子系统之间的交互,使得客户…...

GIS和倾斜摄影的关系?

GIS(地理信息系统)和倾斜摄影是两种在地理空间数据处理和分析中扮演重要角色的技术。但是我们总是会分不清二者,本文就带大家从不同角度了解二者之间的关系。 概念 GIS是一种用来捕获、存储、分析和展示地理空间数据的技术,它可以…...

【CI/CD】图解六种分支管理模型

图解六种分支管理模型 任何一家公司乃至于一个小组织,只要有写代码的地方,就有代码版本管理的主场,初入职场,总会遇到第一个拦路虎 git 管理流程,但是每一个企业似乎都有自己的 git 管理流程,倘若我们能掌握…...

LeetCode105. 从前序与中序遍历序列构造二叉树

105. 从前序与中序遍历序列构造二叉树 文章目录 [105. 从前序与中序遍历序列构造二叉树](https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)一、题目二、题解 一、题目 给定两个整数数组 preorder 和 inorder ,其中 preo…...

编码技巧——Sentinel的blockHandler与fallback

本文介绍Sentinel的blockHandler与fallback的区别,背景是:发生限流时,配置的sentinel的blockhandler没有生效而fallback生效了;排查原因,从而给出Sentinel配置异常降级和限流降级的代码写法; 在查看源码前…...

最新成果展示:GaN基Micro-LED热学模型数据库的开发及应用

由于GaN基Micro-LED表面积-体积比增加,其在热学方面的性质有别于大尺寸的LED,如缺陷复合导致的热效应将在发光区域中产生诸多“热”点,导致发光波长不均匀,这将影响后期显示系统的成像稳定性。针对上述问题,天津赛米卡…...

【Vue3】动态组件

动态组件的基本使用 动态组件(Dynamic Components)是一种在 Vue 中根据条件或用户输入来动态渲染不同组件的技术。 在 Vue 中使用动态组件,可以使用 元素,并通过 is 特性绑定一个组件的名称或组件对象。通过在父组件中改变 is 特…...

Java超级玛丽小游戏制作过程讲解 第五天 创建并完成常量类04

//加载障碍物 try {obstacle.add(ImageIO.read(new File(path"brick.png")));obstacle.add(ImageIO.read(new File(path"soil_up.png")));obstacle.add(ImageIO.read(new File(path"soil_base.png"))); } catch (IOException e) {e.printStackTr…...

设置浏览器兼容

浏览器兼容 css兼容 cursor定义手型  Firefox不支持hand,IE支持pointer  解决方法:统一使用pointercss透明  IE:filter:progid:DXImageTransform.Microsoft.Alpha(style0,opacity60)  Firefox:opacity:0.6  解决…...

Java # List

ArrayList<>() import java.util.ArrayList; // 引入 ArrayList 类ArrayList<E> objectName new ArrayList<>();  // 初始化 常用方法 方法描述add()将元素插入到指定位置的 arraylist 中addAll()添加集合中的所有元素到 arraylist 中clear()删除 arrayl…...

git原理与使用

目录 引入基本操作分支管理远程操作标签管理 引入 假设你的老板要你设计一个文档&#xff0c;当你设计好了&#xff0c;拿给他看时&#xff0c;他并不是很满意&#xff0c;就要你拿回去修改&#xff0c;你修改完后&#xff0c;再给他看时&#xff0c;他还是不满意&#xff0c;…...

【C语言题解】将一句话的单词进行倒置,标点不倒置。

题目描述&#xff1a;将一句话的单词进行倒置&#xff0c;标点不倒置。比如 “I like beijing.”&#xff0c;经过处理后变为&#xff1a;“beijing. like I”。 文章目录 原题目题目描述&#xff1a;输入描述&#xff1a;输出描述&#xff1a;题目链接&#xff1a; 整体思路分…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...