当前位置: 首页 > 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; 整体思路分…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...