设计模式之模版方法
模版方法介绍
模版方法(Template Method)模式是一种行为型设计模式,它定义了一个操作(模板方法)的基本组合与控制流程,将一些步骤(抽象方法)推迟到子类中,使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。这种设计方式将特定步骤的具体实现与操作流程分离开来,实现了代码的复用和扩展,从而提高代码质量和可维护性。
1、模版方法模式的定义与原理
模版方法模式原始定义是:在操作中定义算法的框架,将一些步骤推迟到子类中。模版方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。这里的算法可以理解为广义上的业务逻辑,并不是特指某一个实际的算法。
模版方法模式的主要原理包括:
- 抽象父类:定义一个算法所包含的所有步骤,并提供一些通用的方法逻辑。
- 具体子类:继承自抽象父类,根据需要重写父类提供的算法步骤中的某些步骤。
2、模版方法模式的角色
模版方法模式包含以下主要角色:
- 抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。
- 模板方法(Template Method):定义了算法的骨架,按某种顺序调用其包含的基本方法。
- 基本方法(Concrete Method):在抽象类中已经实现的方法,为算法的各个步骤提供默认实现。
- 抽象方法(Abstract Method):在抽象类中声明,由具体子类实现的方法,用于算法的某些特定步骤。
- 钩子方法(Hook Method):在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。钩子方法提供了算法框架中的扩展点,允许子类在不改变算法结构的情况下,通过重写这些方法来自定义算法的行为。
3、模版方法模式的优点与缺点
优点
- 提高代码复用性:所有的子类可以复用父类中提供的模板方法代码。
- 提高扩展性:框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能。
- 明确算法结构:通过模板方法,可以清晰地定义算法的框架和步骤,使得算法的结构更加明确和易于理解。
缺点
- 类数量增加:由于每个算法都需要一个抽象类和具体子类来实现,因此在操作流程比较多时可能导致类的数量急剧增加,从而导致代码的复杂性提高。
- 关联性高:模板方法与子类实现的抽象方法紧密相关,如果该模板方法需要修改,可能会涉及到多个子类的修改。
4、模版方法模式的应用场景
模版方法模式适用于以下场景:
- 当多个类有共同的算法结构,但具体的实现步骤可能有所不同时。
- 当需要在不改变算法结构的情况下,对算法的某些步骤进行定制时。
- 当需要提高代码的复用性和扩展性时。
例如,在软件开发中,经常需要处理各种业务逻辑流程,这些流程通常具有相似的结构但具体的实现步骤可能因业务需求的不同而有所差异。此时,可以使用模版方法模式来定义这些流程的框架和步骤,然后通过不同的子类来实现具体的业务逻辑。这样可以减少代码的重复,提高代码的可维护性和可扩展性。
二、模版方法实现例子
以下是一个用Java编写的模版方法模式的例子。在这个例子中,我们将创建一个抽象类Game
,它定义了一个游戏的基本流程(即模版方法),包括初始化游戏、玩游戏和结束游戏等步骤。然后,我们创建两个具体的游戏类VideoGame
和BoardGame
,它们分别实现了这些步骤中的特定行为。
// 抽象游戏类
abstract class Game { // 模版方法,定义了游戏的流程 final void play() { initializeGame(); while (!gameOver()) { playStep(); } endGame(); } // 抽象方法,需要子类实现 abstract void initializeGame(); // 抽象方法,需要子类实现 abstract void playStep(); // 抽象方法,判断游戏是否结束,可以提供一个默认实现,也可以留空让子类实现 abstract boolean gameOver(); // 钩子方法,可以在需要时由子类重写 void endGame() { System.out.println("Game Over!"); }
} // 视频游戏类
class VideoGame extends Game { @Override void initializeGame() { System.out.println("Initializing Video Game..."); } @Override void playStep() { System.out.println("Playing Video Game Step..."); // 这里可以添加更多的游戏步骤逻辑 } @Override boolean gameOver() { // 这里简化为总是返回true以结束游戏 // 在实际游戏中,这里应该包含判断游戏是否结束的逻辑 return true; } // 可以选择重写钩子方法以提供自定义的结束游戏逻辑 // 但在这个例子中,我们使用父类的默认实现
} // 桌游类
class BoardGame extends Game { @Override void initializeGame() { System.out.println("Setting up Board Game..."); } @Override void playStep() { System.out.println("Playing Board Game Turn..."); // 这里可以添加更多的游戏回合逻辑 } @Override boolean gameOver() { // 这里简化为总是返回true以结束游戏 // 在实际游戏中,这里应该包含判断游戏是否结束的逻辑 return true; } // 同样,可以选择重写钩子方法
} // 客户端类
public class TemplateMethodPatternDemo { public static void main(String[] args) { Game videoGame = new VideoGame(); System.out.println("Playing Video Game:"); videoGame.play(); Game boardGame = new BoardGame(); System.out.println("\nPlaying Board Game:"); boardGame.play(); }
}
在这个例子中,Game
类定义了一个游戏的模版方法play()
,它按照初始化游戏、玩游戏步骤(循环直到游戏结束)、结束游戏的顺序来执行。initializeGame()
、playStep()
和gameOver()
是抽象方法,需要由子类来实现具体的游戏逻辑。endGame()
是一个钩子方法,它提供了一个默认的实现,但子类可以根据需要重写它。
VideoGame
和BoardGame
类分别实现了Game
类的抽象方法,以提供各自的游戏逻辑。在main
方法中,我们创建了VideoGame
和BoardGame
的实例,并调用了它们的play()
方法来玩游戏。由于play()
方法是final
的,因此它不能被子类重写,这保证了游戏流程的一致性。然而,通过重写抽象方法和钩子方法,子类可以灵活地实现自己的游戏逻辑。
如果觉得不错,记得点赞收藏,你们的反馈是我不断创作的动力。
相关文章:

设计模式之模版方法
模版方法介绍 模版方法(Template Method)模式是一种行为型设计模式,它定义了一个操作(模板方法)的基本组合与控制流程,将一些步骤(抽象方法)推迟到子类中,使得子类可以在…...

docker部署redis/mongodb/
一、redis 创建/root/redis/conf/redis.conf 全部执行命令如下 docker run -it -d --name redis -p 6379:6379 --net mynet --ip 172.18.0.9 -m 400m -v /root/redis/conf:/usr/local/etc/redis -e TXAsia/Shangehai redis redis-server /usr/local/etc/redis/redis.conf 部署…...
LeetCode 581. 最短无序连续子数组
更多题解尽在 https://sugar.matrixlab.dev/algorithm 每日更新。 组队打卡,更多解法等你一起来参与哦! LeetCode 581. 最短无序连续子数组,难度中等。 排序 解题思路:首先对数组排序,然后找出两侧顺序的数组&#x…...

数据库可视化管理工具dbeaver试用及问题处理。
本文记录了在内网离线安装数据库可视化管理工具dbeaver的过程和相关问题处理方法。 一、下载dbeaver https://dbeaver.io/download/ 笔者测试时Windows平台最新版本为:dbeaver-ce-24.1.1-x86_64-setup.exe 二、安装方法 一路“下一步”即可 三、问题处理 1、问…...
29、php实现和为S的两个数字(含源码)
题目:php 实现 和为S的两个数字 描述: 输入一个递增排序的数组和一个数字S,在数组中查找两个数, 是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。 输出描述: 对应每个测…...
Spring Boot中的全局异常处理
Spring Boot中的全局异常处理 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨如何在Spring Boot应用中实现全局异常处理,这是保证应用…...

中英双语介绍美国苹果公司(Apple Inc.)
中文版 苹果公司简介 苹果公司(Apple Inc.)是一家美国跨国科技公司,总部位于加利福尼亚州库比蒂诺。作为全球最有影响力的科技公司之一,苹果以其创新的产品和设计引领了多个科技领域的变革。以下是对苹果公司发展历史、主要产品…...
C语言牢大坠机
目录 开头程序程序的流程图《牢大坠机》结尾 开头 大家好,我叫这是我58,今天,我们要来看关于牢大坠机的一些东西。 程序 #define _CRT_SECURE_NO_WARNINGS 1 #define HIGH 66 #include <stdio.h> #include <Windows.h> int ma…...
zdppy+vue3+antd 实现表格单元格编辑功能
初步实现 <template><a-button class"editable-add-btn" style"margin-bottom: 8px" click"handleAdd">Add</a-button><a-table bordered :data-source"dataSource" :columns"columns"><templa…...
elasticsearch索引怎么设计
Primary Shard(主分片) Primary Shard(主分片)是索引数据存储的基本单位,承担着数据写入和查询的职责。以下是关于Primary Shard的一些关键点: 1. 数据分布:每个索引在创建时会被分成多个主分…...
React 中 useState 和 useReducer 的联系和区别
文章目录 使用场景使用 useState使用 useReducer 联系区别用法状态更新逻辑适用场景可读性和可维护性 使用场景 使用 useState 状态逻辑简单。只涉及少量的状态更新。需要快速和简单的状态管理。 使用 useReducer 状态逻辑复杂。涉及多个子状态或多种状态更新逻辑。需要更好…...
Linux 定时任务详解:全面掌握 cron 和 at 命令
Linux 定时任务详解:全面掌握 cron 和 at 命令 Linux 系统中定时任务的管理对于运维和开发人员来说都是至关重要的。通过定时任务,可以在特定时间自动执行脚本或命令,提高系统自动化程度。本文将详细介绍 Linux 中常用的定时任务管理工具 cr…...

力扣考研经典题 反转链表
核心思想 头插法: 不断的将cur指针所指向的节点放到头节点之前,然后头节点指向cur节点,因为最后返回的是head.next 。 解题思路 1.如果头节点是空的,或者是只有一个节点,只需要返回head节点即可。 if (head null …...
opencv 设置超时时间
经常爬视频数据,然后用opencv做成图片 因此设置超时时间很重要 cap.set(cv2.CAP_PROP_FPS, timeout_ms) for idx, row in data.iterrows(): if idx < 400: continue try: # 打开视频文件 timeout_ms 5000 cap cv2.VideoCapture(row[PLAY_URL]) cap.set(cv2.C…...
2024年7月6日随笔
期末考试全部结束了,这个月是真累啊,一堆事,好在都熬过来了,上次参加的那个码题杯自己居然进国赛了,我看了一下职业赛道和本科赛道的题,本科赛道的感觉要难上不少,比赛时间是一周后,…...
Ubuntu 打开或关闭界面
设置开机默认关闭图形界面 1. 设置系统默认启动到多用户目标(命令行界面): o 使用以下命令将系统默认启动目标设置为多用户目标(这会关闭图形界面): sudo systemctl set-default multi-use…...

使用京东云主机搭建幻兽帕鲁游戏联机服务器全流程,0基础教程
使用京东云服务器搭建幻兽帕鲁Palworld游戏联机服务器教程,非常简单,京东云推出幻兽帕鲁镜像系统,镜像直接选择幻兽帕鲁镜像即可一键自动部署,不需要手动操作,真正的新手0基础部署幻兽帕鲁,阿腾云整理基于京…...

Python和MATLAB微机电健康推导算法和系统模拟优化设计
🎯要点 🎯惯性测量身体活动特征推导健康状态算法 | 🎯卷积网络算法学习惯性测量数据估计六自由度姿态 | 🎯全球导航卫星系统模拟,及惯性测量动态测斜仪算法、动态倾斜算法、融合算法 | 🎯微机电系统加速度…...

IT之家最新科技热点 | 小米 AI 研究院开创多模态通用模型
人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…...

黑色矩形块检测数据集VOC+YOLO格式2000张1类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2000 标注数量(xml文件个数):2000 标注数量(txt文件个数):2000 标注…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...

Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...

Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...