设计模式--模板方法模式(Template Method Pattern)
一、什么是模板方法模式(Template Method Pattern)
模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一个算法的骨架,将一些步骤的实现延迟到子类中。模板方法模式允许在不改变算法的结构的情况下,通过在子类中重写特定步骤的具体实现,来改变算法的部分行为。
模板方法模式通常包括以下几个角色:
- 抽象类(Abstract Class):定义了一个模板方法,其中包含了算法的骨架,包括一系列步骤的调用顺序和约定。这些步骤可以是具体的方法,也可以是抽象的,留给子类实现。
- 具体子类(Concrete Subclasses):实现了抽象类中定义的抽象方法,以提供具体步骤的实现,从而完成整个算法。
模板方法模式的主要优点包括:
- 代码重用性:通过将算法的公共部分放在抽象类中,可以避免在每个具体子类中重复编写相同的代码。
- 灵活性:可以通过子类的不同实现来定制和扩展算法的部分行为,而不需要修改算法的整体结构。
- 易于维护:将算法分解成一系列步骤,每个步骤都有明确的功能,使得代码更易于理解和维护。
模板方法模式常见于许多框架和库中,例如:
- 在GUI框架中,窗口和对话框的创建过程通常遵循模板方法模式。
- 数据库连接和操作的过程也可以使用模板方法模式来定义通用的连接和断开操作,具体数据库的实现由子类完成。
总之,模板方法模式通过定义算法骨架和具体步骤的分离,实现了代码重用、定制和易维护的目标。
二、模板方法模式的现实应用场景
一个现实中常见的应用模板方法模式的场景是咖啡和茶的制作过程。这两种饮料的制作过程有一些共同的步骤,但在其中的某些步骤上有所不同,因此可以使用模板方法模式来实现这种共同和变化的结构。
假设我们有一个名为"Beverage"的抽象类,它定义了制作饮料的模板方法。在这个模板方法中,包含了制作饮料的通用步骤,如加热水、冲泡、倒入杯中等。然后,我们有两个具体子类,“Coffee"和"Tea”,它们分别实现了抽象类中的特定步骤,以适应不同的饮料。
以下是示例代码:
// 抽象类
abstract class Beverage {final void prepareBeverage() {boilWater();brew();pourInCup();addCondiments();}abstract void brew();abstract void addCondiments();void boilWater() {System.out.println("Boiling water");}void pourInCup() {System.out.println("Pouring into cup");}
}// 具体子类 Coffee
class Coffee extends Beverage {void brew() {System.out.println("Dripping coffee through filter");}void addCondiments() {System.out.println("Adding sugar and milk");}
}// 具体子类 Tea
class Tea extends Beverage {void brew() {System.out.println("Steeping the tea");}void addCondiments() {System.out.println("Adding lemon");}
}
在这个例子中,抽象类"Beverage"定义了模板方法prepareBeverage(),它包含了制作饮料的通用步骤。具体子类"Coffee"和"Tea"分别实现了不同的步骤,以制作咖啡和茶。这样,我们可以保留通用的制作流程,并在具体子类中实现特定的细节步骤。
通过使用模板方法模式,我们可以避免在每个具体子类中重复编写相同的制作步骤,同时也能很方便地扩展和修改制作流程,而不必改变整体结构。这个例子展示了模板方法模式在实际应用中的使用。
三、使用模板方法模式需要注意的问题
在使用模板方法模式时,需要注意一些问题,以确保正确地应用该模式并避免潜在的陷阱:
- 过度复杂化:过度使用模板方法模式可能导致代码过于复杂,因为模板方法模式的设计理念是将通用的流程提取出来,但有时可能会引入不必要的抽象和层级,导致代码难以理解和维护。
- 灵活性和变化:模板方法模式主要用于处理固定的算法结构,如果算法的变化点过多,可能会导致模板方法模式不够灵活,需要频繁修改模板和子类。
- 继承限制:使用模板方法模式意味着子类必须遵循父类定义的流程,如果不满足这种流程,可能需要强行适应,从而破坏了设计的灵活性。
- 破坏开放封闭原则:如果在模板方法中增加新的步骤,需要同时修改所有子类,这可能违反了开放封闭原则,即对扩展开放,对修改封闭。
- 复杂的继承结构:随着项目的发展,可能会出现多级继承结构,导致难以维护和理解。
- 不易于单元测试:由于模板方法的实际行为由多个子类共同决定,因此在单元测试时可能需要考虑更多的因素。
- 违反单一职责原则:在抽象类中包含了多个步骤的实现,可能导致抽象类功能过于复杂,违反了单一职责原则。
为了更好地应用模板方法模式,可以考虑以下策略:
- 谨慎使用:只在确实有共同流程的算法中使用模板方法模式,避免过度设计。
- 合理抽象:确保抽象类和具体子类之间的关系适当,并且继承结构不会过于复杂。
- 钩子方法:通过在抽象类中添加钩子方法,允许子类对流程进行部分修改。
- 策略模式替代:在一些变化较大的情况下,可以考虑使用策略模式,将算法的不同部分作为策略进行组合。

相关文章:
设计模式--模板方法模式(Template Method Pattern)
一、什么是模板方法模式(Template Method Pattern) 模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一个算法的骨架,将一些步骤的实现延迟到子类中。模板方法模式允许在不改变算法的…...
linux 权限管理命令
权限管理命令 权限的查看及含义 可以使用ls -l来查看每个文件或目录的权限,一共有十位 ls -ls--------------------------------------------------------------------rw-------. 1 root root 946 Feb 14 16:13 anaconda-ks.cfgdrwxr-xr-x. 2 root root 4096 Feb…...
c++ qt--线程(一)(第八部分)
c qt–线程(一)(第八部分) 一.进程(Process) 在任务管理器中的进程页下,可以看到进程,任务管理器将进程分为了三类,应用、后台进程、window进程 应用: 打开…...
参数初始化方法
梯度消失与梯度爆炸 考虑一个 3 层的全连接网络。 H 1 X W 1 H{1}X \times W{1} H1XW1, H 2 H 1 W 2 H{2}H{1} \times W{2} H2H1W2, O u t H 2 W 3 OutH{2} \times W_{3} OutH2W3 其中第 2 层的权重梯度如下: Δ W 2 ∂ L o s s …...
Go的基础运行方式和打包
目录 基础运行方式导入路径 打包技巧相关知识点 基础运行方式 // 文件名可以不是main,但包名和入口函数比如是main // main.go package main // 导入包的时候可以直接导入,也可以导入后指定包名, import ("fmt"godemo "githu…...
Deepin 图形化部署 Hadoop Single Node Cluster
Deepin 图形化部署 Hadoop Single Node Cluster 升级操作系统和软件 快捷键 ctrlaltt 打开控制台窗口 更新 apt 源 sudo apt update更新 系统和软件 sudo apt -y dist-upgrade升级后建议重启 开启ssh服务 打开资源管理器 进入系统盘 找到 etc 目录 在系统盘的 etc 目录上 右键…...
23款奔驰GLS400升级柏林之声音响系统,体验不一样的感觉
Burmester 环绕立体声音响系统–为每位乘员打造令人印象深刻的音质13个高性能扬声器、总功率为590瓦的9声道数字信号处理器(DSP)放大器以及放大器/扬声器系统专为车辆配置,打造出一流的Burmester之音。必要时还可进一步提升令人印象深刻的听觉体验。声音环绕功能能够…...
Vue的map()方法和filter()方法的使用
map() map():方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值 案例: const data res.map(item > item.id); const data res.map(item > return item.id); const data res.map(item > { name: item.name, id…...
qt创建临时文件
1、临时文件系统 在 Linux 系统中,创建临时文件系统很简单,执行如下指令即可: mount -t tmpfs -o size1024m tmpfs /mnt/tmp 挂载成功后,在 /mnt/tmp 这个挂载点下创建的所有文件都将会是临时文件, 也就是说:当电脑关…...
Element——table排序,上移下移功能。及按钮上一条下一条功能
需求:table排序,可操作排序上移下移功能。判断第一行上移禁用和最后一行下移禁用,排序根据后端返回的字段 <el-table:data"tableData"style"width: 100%"><el-table-column type"index" label"序…...
无涯教程-Android - Linear Layout函数
Android LinearLayout是一个视图组,该视图组将垂直或水平的所有子级对齐。 Linear Layout - 属性 以下是LinearLayout特有的重要属性- Sr.NoAttribute & 描述1 android:id 这是唯一标识布局的ID。 2 android:baselineAligned 此值必须是布尔值,为…...
ELK安装、部署、调试(六) logstash的安装和配置
1.介绍 Logstash是具有实时流水线能力的开源的数据收集引擎。Logstash可以动态统一不同来源的数据,并将数据标准化到您选择的目标输出。它提供了大量插件,可帮助我们解析,丰富,转换和缓冲任何类型的数据。 管道(Logs…...
【Spring Security】UserDetails 接口介绍
文章目录 UserDetails 的作用UserDetails 接口中各个方法详解 UserDetails 的作用 UserDetails 在 Spring Security 框架中主要担任获取用户信息的接口,通过该接口就能拿到用户的信息和验证用户的信息,这些信息在下面的方法中会有讲述。 UserDetails 接…...
C# Linq源码分析之Take(四)
概要 本文主要对Take的优化方法进行源码分析,分析Take在配合Select,Where等常用的Linq扩展方法使用时候,如何实现优化处理。 本文涉及到Select, Where和Take和三个方法的源码分析,其中Select, Where, Take更详尽的源码分析&…...
Python 和 C++ 使用细节差别
1. 循环中的可迭代对象长度 1. 循环中的可迭代对象长度 C 中,for循环中写明a.size(),每次循环这个值是重新计算的; # include “iostream” # include <vector> using namespace std;int main() {vector<int> a(10);int cnt 0…...
在Ubuntu Linux系统上安装RabbitMQ服务并解决公网远程访问问题
文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…...
葫芦娃自动预约-公众号代挂
效果 #小程序://航旅黔购/1nkYlNRVzm0Gg9x #小程序://贵旅优品/7zz6mtnSVgDfyqa #小程序://新联惠购/ibFdsuhWqIbczEd #小程序://贵盐黔品/u2TgExCUdkavrFe #小程序://空港乐购/ANkOOdqEeo71kah #小程序://遵航出山/ZkR7DQy1raoPxKD #小程序://乐旅商城/Ip5cgpJ7TLmRrWF #小程序…...
ESP32应用教程(0)— PMW3901MB光流传感器
文章目录 前言 1 传感器介绍 1.1 关键特征 1.2 关键参数 2 硬件概述 2.1 信号引脚 2.2 参考电路图 3 寄存器 3.1 寄存器列表 3.2 性能优化寄存器 4 代码说明 4.1 结构体说明 4.2 编译说明 5 波形分析 前言 本文介绍了在 ESP32 DEVKIT V1 开发板上开发 PMW3901MB…...
docker部署nginx,部署springboot项目,并实现访问
一、先部署springboot项目 1、安装docker: yum install docker -y 2、启动docker: service docker start 重启: service docker restart 3、查看版本: docker -v 4、使设置docker.service生效(路径:…...
十五、模板方法模式
一、什么是模板方法模式 模板方法(Template Method)模式的定义如下:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。 模板方法模式包含以…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
