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

设计模式-08 - 模板方法模式 Template Method


设计模式-08 - 模板方法模式 Template Method
 
1.定义

模板方法模式是一种设计模式,它定义了一个操作的骨架,而由子类来决定如何实现该操作的某些步骤。它允许子类在不改变算法结构的情况下重定义算法的特定步骤。
 
模板方法模式适合用于以下情况:

需要定义一个算法的骨架,但允许子类实现特定步骤:例如,一个排序算法,其中骨架定义了排序过程,而子类定义了具体的比较方法。
需要避免在子类中重复代码:例如,一个图形绘制框架,其中抽象类定义了绘制过程的骨架,而子类定义了绘制特定形状的具体方法。
需要提供算法的可扩展性和灵活性:例如,一个游戏引擎,其中抽象类定义了游戏循环的骨架,而子类定义了特定游戏玩法的具体步骤。

2.内涵

模板方法模式具有以下优点

可扩展性:通过允许子类重定义某些步骤,模板方法模式提供了很大的可扩展性。
代码复用:模板方法模式允许在抽象类中定义算法的骨架,从而避免在子类中重复代码。
灵活性:子类可以根据需要自定义算法的特定步骤,从而提供灵活性。


模板方法模式也有一些缺点

可能难以理解:模板方法模式可能难以理解,尤其是对于大型和复杂的算法。
难以调试:由于算法的骨架在抽象类中定义,因此可能难以调试子类中的特定步骤。


3.使用示例
#include <iostream>// Step 1: Template Method (Abstract Class)  定义模板
class VehicleTemplate {
public:// Template method defines the algorithm structurevoid buildVehicle() {assembleBody();installEngine();addWheels();std::cout << "Vehicle is ready!\n";}// Abstract methods to be implemented by concrete classesvirtual void assembleBody() = 0;virtual void installEngine() = 0;virtual void addWheels() = 0;
};// Step 2: Concrete Classes  具体实现类
class Car : public VehicleTemplate {
public:void assembleBody() override {std::cout << "Assembling car body.\n";}void installEngine() override {std::cout << "Installing car engine.\n";}void addWheels() override {std::cout << "Adding 4 wheels to the car.\n";}
};class Motorcycle : public VehicleTemplate {
public:void assembleBody() override {std::cout << "Assembling motorcycle frame.\n";}void installEngine() override {std::cout << "Installing motorcycle engine.\n";}void addWheels() override {std::cout << "Adding 2 wheels to the motorcycle.\n";}
};// Step 3: Client Code  客户端调用代码
int main() {std::cout << "Building a Car:\n";Car car;car.buildVehicle();std::cout << "\nBuilding a Motorcycle:\n";Motorcycle motorcycle;motorcycle.buildVehicle();return 0;
}
 
4.注意事项

在使用模板方法模式时,需要注意以下事项:

  • 算法的灵活性:确保算法的骨架足够灵活,以允许子类根据需要自定义算法的特定步骤。
  • 抽象和具体方法的平衡:抽象类应仅包含算法的骨架,而具体子类应包含算法的具体实现。避免在抽象类中包含具体细节,因为这会降低可扩展性。
  • 继承层次结构:仔细考虑继承层次结构,并确保子类不会引入不必要的复杂性或冗余。
  • 可测试性:确保抽象类和具体子类都可测试,以验证算法的正确性。
  • 性能影响:模板方法模式可能引入一些性能开销,因为需要在运行时调用模板方法和具体方法。在对性能敏感的应用程序中,需要考虑这种开销。


此外,还有一些最佳实践可以提高模板方法模式的使用效果:

  • 使用钩子方法:钩子方法是抽象类中可选的方法,允许子类在不重写整个模板方法的情况下自定义算法的特定方面。
  • 提供默认实现:对于某些步骤,可以提供默认实现,以简化子类的实现。
  • 使用多态性:利用多态性来允许子类在运行时替换算法的具体步骤。
  • 考虑使用策略模式:在某些情况下,策略模式可以是模板方法模式的替代方案,它允许算法的变体完全由策略对象决定。
 
5.最佳实践


模板方法模式的最佳实践,避免错误的最佳经验:

  • 明确定义算法的骨架:抽象类应明确定义算法的骨架,包括其步骤和顺序。避免在抽象类中包含具体细节。
  • 只在具体子类中实现具体步骤:具体子类应仅实现算法的具体步骤,而不要改变算法的整体结构。
  • 使用钩子方法:钩子方法允许子类在不重写整个模板方法的情况下自定义算法的特定方面。这可以提高灵活性并避免不必要的代码重复。
  • 提供默认实现:对于某些步骤,可以提供默认实现,以简化子类的实现。默认实现应涵盖常见情况,而子类可以根据需要重写它们。
  • 考虑使用策略模式:在某些情况下,策略模式可以是模板方法模式的替代方案,它允许算法的变体完全由策略对象决定。策略模式可以提供更大的灵活性,但可能更复杂。
  • 确保可测试性:抽象类和具体子类都应可测试,以验证算法的正确性。使用单元测试可以确保算法在各种情况下都能按预期工作。
  • 考虑性能影响:模板方法模式可能引入一些性能开销,因为需要在运行时调用模板方法和具体方法。在对性能敏感的应用程序中,需要考虑这种开销。

 
6.总结
 

模板方法模式适合用于以下情况:

  • 需要定义一个算法的骨架,但允许子类实现特定步骤:例如,一个排序算法,其中骨架定义了排序过程,而子类定义了具体的比较方法。
  • 需要避免在子类中重复代码:例如,一个图形绘制框架,其中抽象类定义了绘制过程的骨架,而子类定义了绘制特定形状的具体方法。
  • 需要提供算法的可扩展性和灵活性:例如,一个游戏引擎,其中抽象类定义了游戏循环的骨架,而子类定义了特定游戏玩法的具体步骤。

总体而言,模板方法模式是一种强大的设计模式,可以提高代码的可扩展性、复用性和灵活性。通过仔细考虑上述注意事项和最佳实践,可以有效地使用该模式来设计和实现复杂的算法。
 

相关文章:

设计模式-08 - 模板方法模式 Template Method

设计模式-08 - 模板方法模式 Template Method 1.定义 模板方法模式是一种设计模式&#xff0c;它定义了一个操作的骨架&#xff0c;而由子类来决定如何实现该操作的某些步骤。它允许子类在不改变算法结构的情况下重定义算法的特定步骤。 模板方法模式适合用于以下情况&am…...

Android 适配阿拉伯语之vector图标镜像

Android 适配阿拉伯语之vector图标镜像 android:autoMirrored“true” 属性简单而直接的方法来自动处理 RTL 环境中图标的翻转。 使用 android:autoMirrored“true” 在 Vector Drawable 中是一种非常方便的方法&#xff0c;因为它允许你使用相同的 drawable 资源来适应不同的…...

推荐4个可用的github国内镜像

Github是全球最大的代码托管云平台&#xff0c;超过1亿用户在平台上分享代码及数据&#xff0c;深受生物信息学软件开发者的喜爱&#xff0c;并且现在发表文章&#xff0c;若涉及到代码&#xff0c;编辑还要求我们把代码及数据存放在github上&#xff0c;以便检查数据的真实性和…...

从项目开始学习Vue——02(若依框架)

往期&#xff1a; 从项目开始学习Vue——01 目录标题 一、基础插件&#xff08;一&#xff09;路由Vue Router&#xff08;二&#xff09;导航守卫&#xff08;路由拦截器&#xff09;二、Vuex&#xff08;一&#xff09;什么是VuexVuex的部分介绍内容&#xff1a; &#xff08…...

使用JavaScript日历小部件和DHTMLX Gantt的应用场景(二)

DHTMLX Suite UI 组件库允许您更快地构建跨平台、跨浏览器 Web 和移动应用程序。它包括一组丰富的即用式 HTML5 组件&#xff0c;这些组件可以轻松组合到单个应用程序界面中。 DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表&#xff0c;可满足项目管理应用…...

springboot整合redis多数据源(附带RedisUtil)

单数据源RedisUtil(静态) 单数据源RedisUtil,我这里implements ApplicationContextAware在setApplicationContext注入redisTemplate,工具类可以直接类RedisUtil.StringOps.get()使用 package com.vehicle.manager.core.util;import com.alibaba.fastjson.JSON; import lombok.e…...

Web实时通信的学习之旅:SSE(Server-Sent Events)的技术详解及简单示例演示

文章目录 一、什么是SSE二、SSE技术的基本原理三、SSE适用于场景四、Node服务端示例1、协议2、格式3、事件3.1、事件3.2、事件唯一标识符3.3、重连事件 4、具体示例 五、客户端示例1、检测客户端是否支持SSE2、创建客户端连接3、事件监听4、接收事件5、自定义事件6、错误处理7、…...

Apache Flume事务

Apache Flume 中的事务处理是指 Flume Agent 在处理事件流时的一种机制&#xff0c;用于确保数据的可靠传输和处理。 1. 事务概述&#xff1a; Flume 中的事务是指一组事件的传输和处理&#xff0c;这些事件在传输过程中要么全部成功完成&#xff0c;要么全部失败&#xff0…...

根据部门id删除该部门下的员工(事务)

application.properties&#xff1a; 或&#xff1a; application.yml&#xff1a; 新表&#xff1a; 日志对象类&#xff1a; 日志service类&#xff1a; 日志service接口&#xff1a; 日志mapper类&#xff1a; 部门service类&#xff1a; 员工mapper类&#xff1a;...

Java之String类

一、String类常用方法 1.引用类型的比较 我们知道在Java中两个引用遍历是不能用" "号来比较的&#xff0c;而String类重写了父类objects的equals方法&#xff0c; 实现了引用类型的比较 例子 import java.util.Scanner; public class Main { public static void…...

es终止快照恢复进程的方法

方法1、删除索引可以终止&#xff0c;恢复进程。 DELETE index_* // 按通配符删除以index_开头的索引 DELETE _all // 删除全部索引 POST *,-.*/_close 关闭索引 POST *,-.*/_open 打开索引 DELETE *,-.* 删除全部索引方法2、强制重启es 集群也可也终…...

ubantu安装rabbbitmq

ubantu安装rabbbitmq 安装Erlang1、在linux下直接安装2、上传Erlang文件后解压 安装rabbitmq开启web管理接口创建用户及修改guest密码&#xff0c;删除guest默认账号 安装Erlang 1、在linux下直接安装 #运行以下命令直接安装&#xff1a; sudo apt-get install erlang#可运行…...

了解 条码工具 Dynamsoft 在条码读取器中的形态运算

在图像处理中&#xff0c;术语形态学是指分析形状以填充小孔、去除噪声、提取轮廓等的一组操作。形态学操作很像空间卷积中的过滤过程。有两个部分在起作用&#xff1a;结构元素和预定义的计算规则。 点击下载Dynamsoft最新版https://www.evget.com/product/3691/download 结…...

NIO和NIO.2对比

Java NIO (New Input/Output) 是从Java 1.4版本开始引入的一个新的I/O API&#xff0c;用于替代原来的BIO&#xff08;Blocking I/O&#xff09;API。NIO提供了更加灵活和高效的网络通信方式&#xff0c;特别适合于高吞吐量的网络编程。NIO的主要特点是非阻塞模式&#xff0c;它…...

Google准备好了吗?OpenAI发布ChatGPT驱动搜索引擎|TodayAI

在科技界波澜壮阔的发展中&#xff0c;OpenAI正式宣布其最新突破——一个全新的基于ChatGPT技术的搜索引擎&#xff0c;旨在直接挑战谷歌在搜索领域的统治地位。这一创新将可能彻底改变用户上网搜索的方式。 据悉&#xff0c;这款AI驱动的搜索引擎利用了ChatGPT的强大功能&…...

乐观锁、悲观锁、互斥锁、读写锁

乐观锁和悲观锁是两种不同的锁机制&#xff0c;用于在多线程环境下解决资源竞争问题。互斥锁和读写锁是两种常见的锁类型&#xff0c;它们都可以用来实现乐观锁或悲观锁。 乐观锁 是一种无锁机制&#xff0c;它假设在多线程环境下对共享资源的操作不会发生冲突&#xff0c;因…...

Gin入门指南:从零开始快速掌握Go Web框架Gin

官网:https://gin-gonic.com/ GitHub:https://github.com/gin-gonic 了解 Gin Gin 是一个使用 Go 语言开发的 Web 框架,它非常轻量级且具有高性能。Gin 提供了快速构建 Web 应用程序所需的基本功能和丰富的中间件支持。 以下是 Gin 框架的一些特点和功能: 快速而高效:…...

Scala里的class、object、case class、case object 、trait

Class&#xff08;类&#xff09; 定义和作用 Scala 中的 class 是一种蓝图&#xff0c;用于创建对象&#xff08;实例&#xff09;。它定义了对象的状态和行为。类可以包含字段&#xff08;属性&#xff09;和方法&#xff08;函数&#xff09;。类可以有构造器&#xff0c;…...

移动端自动化测试工具 Appium 之 main 启动

文章目录 一、背景二、生成xml文件2.1、创建xml方法2.2、执行主类MainTest2.3、自动生成的xml2.4、工程目录2.5、执行结果 三、命令行执行appium服务四、主方法启动类五、集成Jenkins六、总结 一、背景 Jenkins 做集成测试是不错的工具&#xff0c;那么UI自动化是否可以&#…...

WT32-ETH01作为TCP Client进行通讯

目录 模块简介WT32-ETH01作为TCP Client设置电脑作为TCP Server设置连接并进行通讯总结 模块简介 WT32-ETH01网关主要功能特点: 采用双核Xtensa⑧32-bit LX6 MCU.集成SPI flash 32Mbit\ SRAM 520KB 支持TCP Server. TCP Client, UDP Server. UDP Client工作模式 支持串口、wif…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...