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

设计模式之模版方法模式(Template)

一、模版方法模式介绍

1、模版方法模式定义:

     模板方法模式(template method pattern)原始定义是:在操作中定义算法的框架,将一些

     步骤推迟到子类中。模板方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。

     模板方法中的算法可以理解为广义上的业务逻辑,并不是特指某一个实际的算法。

     定义中所说的算法的框架就是模板, 包含算法框架的方法就是模板方法。

     模板方法模式是一种基于继承的代码复用技术,它是一种类行为模式。

     模板方法模式其结构中只存在父类与子类之间的继承关系。

     模板方法的作用主要是提高程序的复用性和扩展性:

            1)复用指的是,所有的子类可以复用父类中提供的模板方法代码

            2)扩展指的是,框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架

                  源码的情况下,基于扩展点定制化框架的功能。

            如: 我们去医院看病一般要经过以下4个流程:挂号、取号、排队、医生问诊等,其中挂

                  号、 取号 、排队对每个病人是一样的,可以在父类中实现,但是具体医生如何根据

                  病情开药每个人都是不一样的,所以开药这个操作可以延迟到子类中实现。

二、模版方法模式原理

1、模版方法模式角色

       模板方法模式的定位很清楚,就是为了解决算法框架这类特定的问题,同时明确表示需要

       使用继承的结构。

       模版方法模式类图如下:

               

       模版方法模式包含如下角色:

              抽象父类:定义一个算法所包含的所有步骤,并提供一些通用的方法逻辑。

                                抽象父类:负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个

                                基本方法构成。

              具体子类:继承自抽象父类,根据需要重写父类提供的算法步骤中的某些步骤。

              模版方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。

              基本方法:是实现算法各个步骤的方法,是模板方法的组成部分。

              基本方法又可以分为三种:

                     1)抽象方法(Abstract Method) :一个抽象方法由抽象类声明、由其具体子类实现。

                     2)具体方法(Concrete Method) :一个具体方法由一个抽象类或具体类声明并实现,

                           其子类可以进行覆盖也可以直接继承。

                     3)钩子方法(Hook Method) :在抽象类中已经实现,包括用于判断的逻辑方法和需

                          要子类重写的空方法两种。

                          一般钩子方法是用于判断的逻辑方法,这类方法名一般为isXxx,返回值类型为

                          boolean类型。

2、用代码表示模版方法模式,

     代码如下:

******************************************************** 抽象父类** @author lbf*******************************************************/
public abstract class AbstractClassTemplate {//模版方法void step1(String key){System.out.println("在模板类中 -> 执行步骤1");if(step2(key)){step3();}else{step4();}step5();}//钩子方法boolean step2(String key){System.out.println("在模板类中 -> 执行步骤2");if("x".equals(key)){return true;}return false;}//基本方法abstract void step3();//基本方法abstract void step4();//基本方法void step5(){System.out.println("在模板类中 -> 执行步骤5");}void run(String key){step1(key);}
}/******************************************************** 具体子类A** @author lbf********************************************************/
public class ConcreteClassA extends AbstractClassTemplate{@Overridevoid step3() {System.out.println("在子类A中 -> 执行步骤 3");}@Overridevoid step4() {System.out.println("在子类A中 -> 执行步骤 4");}
}/******************************************************** 具体子类B** @author lbf*******************************************************/
public class ConcreteClassB extends AbstractClassTemplate{@Overridevoid step3() {System.out.println("在子类B中 -> 执行步骤 3");}@Overridevoid step4() {System.out.println("在子类B中 -> 执行步骤 4");}
}

三、模版方法模式应用示例

       以P2P公司的借款系统中有一个利息计算模块为例来看下模版方法模式的使用;

       利息的计算流程是这样的:

              1)用户登录系统,登录时需要输入账号密码,如果登录失败(比如用户密码错误),

                   系统需要给出提示

              2)如果用户登录成功,则根据用户的借款的类型不同,使用不同的利息计算方式进

                   行计算,系统需要显示计算的利息。

        示例代码如下:

/******************************************************** 账户类--抽象父类** @author lbf* @date 2024-11-06 22:14*******************************************************/
public abstract class Account {//step1 具体方法-验证用户信息是否正确public boolean validate(String account,String password){System.out.println("账号: " + account + ",密码: " + password);if(account.equalsIgnoreCase("tom") &&password.equalsIgnoreCase("123456")){return true;}else{return false;}}//step2 抽象方法-计算利息public abstract void calculate();//step3 具体方法-显示利息public void display(){System.out.println("显示利息!");}//模板方法public void handle(String account,String password){if(!validate(account,password)){System.out.println("账户或密码错误!!");return;}calculate();display();}
}/******************************************************** 借款1个月--具体子类* @author lbf* @date 2024-11-06 22:15*******************************************************/
public class LoanOneMonth extends Account{@Overridepublic void calculate() {System.out.println("借款周期30天,利率为10%!");}}/******************************************************** 借款7天--具体子类* @author lbf* @date 2024-11-06 22:16*******************************************************/
public class LoanSevenDays extends Account{@Overridepublic void calculate() {System.out.println("借款周期7天,无利息!仅收取贷款金额1%的服务费!");}@Overridepublic void display() {System.out.println("七日内借款无利息!");}
}/********************************************************* @author lbf* @date 2024-11-06 22:16*******************************************************/
public class Test {public static void main(String[] args) {Account a1 = new LoanSevenDays();a1.handle("tom","12345");System.out.println("==========================");Account a2 = new LoanOneMonth();a2.handle("zhudy","123456789");}
}

四、模版方法模式总结

1、模版方法模式优点

      1)在父类中形式化的定义一个算法,而由它的子类来实现细节处理,在子类实现详细的

           处理代码时,并不会改变父类算法中步骤的执行顺序

      2)模板方法可以实现一种反向的控制结构,通过子类覆盖父类的钩子方法,来决定某一个

           特定步骤是否需要执行

      3)在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法

           的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则


2、模版方法模式缺点

      1)对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,

            设计也更加抽象

      2)父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向

            的控制结构,它提高了代码阅读的难度。

3、模版方法模式适用场景

      1)多个类有相同的方法并且逻辑可以共用时;

      2)将通用的算法(业务流程)或固定流程设计为模板,在每一个具体的子类中再继续

           优化算法步骤或流程步骤时;

      3)重构超长代码时,发现某一个经常使用的公有方法。

相关文章:

设计模式之模版方法模式(Template)

一、模版方法模式介绍 1、模版方法模式定义: 模板方法模式(template method pattern)原始定义是:在操作中定义算法的框架,将一些 步骤推迟到子类中。模板方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。 模板方法中的算法可以理…...

背包九讲——背包问题求具体方案

目录 背包问题求具体方案 1. 01 背包问题 题目:12. 背包问题求具体方案 - AcWing题库 算法思路: 代码实现: 2. 多重背包问题 算法思路: 3. 完全背包问题 算法思路: 代码实现: 背包问题第九讲—…...

Python http打印(http打印body)flask demo(http调试demo、http demo、http printer)

文章目录 代码解释 代码 # flask_http_printer.pyfrom flask import Flask, request, jsonify import jsonapp Flask(__name__)app.route(/printinfo, methods[POST]) def print_info():# 分隔符separator "-" * 60# 获取请求头headers request.headers# 获取 JS…...

JSF HTML标签教程一口气讲完!(下)

JSF OutputScript示例 JSF教程 - JSF OutputScript示例 h:outputScript标记渲染类型为“script"的HTML元素&#xff0c;类型为“text/javascript"。 此标记将外部JavaScript文件添加到JSF页面。 以下JSF标记 <h:outputScript library"js" name"…...

cmake报错The link interface of target “gRPC::grpc“ contains: OpenSSL::SSL 解决

系统环境&#xff1a;麒麟V10 报错描述&#xff1a; The link interface of target "gRPC::grpc" contains: OpenSSL::SSL but the target was not found. Possible reasons include: * There is a typo in the target name. * A find_package call is missing fo…...

C语言PythonBash:空白(空格、水平制表符、换行符)与转义字符

C语言 空白 C语言中的空白&#xff08;空格、水平制表符、换行符&#xff09;被用于分隔Token&#xff0c;因此Token间可以有任意多个空白。 // 例1 printf("Hello, World!"); 例1中存在5个Token&#xff0c;分别是&#xff1a; printf("Hello, World! \n&qu…...

【Python】轻松解析JSON与XML:Python标准库的json与xml模块

轻松解析JSON与XML&#xff1a;Python标准库的json与xml模块 在现代数据处理与交换中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;和XML&#xff08;eXtensible Markup Language&#xff09;是最常用的两种数据格式。它们广泛应用于API数据传输、配置…...

物联网对商业领域的影响

互联网彻底改变了通信方式&#xff0c;并跨越了因地理障碍造成的人与人之间的鸿沟。然而&#xff0c;物联网&#xff08;IoT&#xff09;的引入通过使设备能够连接到互联网&#xff0c;改变了设备的功能。想象一下&#xff0c;你的闹钟连接到互联网&#xff0c;并且能够用你的声…...

第16章 SELECT 底层执行原理

一、SELECT查询的完整结构 1.1 方式一&#xff08;SQL 92语法&#xff09; SELECT ..., ..., ... FROM ..., ..., ... WHERE 多表的连接条件 AND 不包含组函数的过滤条件 GROUP BY ..., ... HAVING 包含组函数的过滤条件 ORDER BY ... ASC/DESC LIMIT ..., ... 1.2 方式二&a…...

python查询日志,并组装sql,修复缺失的数据

前言 由于mysql链接超时波动&#xff0c;导致数据缺失&#xff0c;需要根据日志填补数据 流程 获取确实数据的订单列表 搜索日志&#xff0c;获取请求日志 根据请求日志拼装sql 打印sql供修复数据 代码 因为我们日志打印的有问题&#xff0c;所以这里用字符串截取获取入…...

RecyclerView进阶知识讲解

在 Android 开发中&#xff0c;RecyclerView 是一种高效的列表和网格布局控件&#xff0c;用于显示大规模数据。尽管基本使用方法简单&#xff0c;但深入理解并掌握其高级进阶用法能大幅提升用户体验和应用性能。下面&#xff0c;我将从布局管理、动画和手势、自定义缓存、优化…...

C语言 函数

时间&#xff1a;2024.11.10-11.11 一、学习内容 1、什么是函数 函数&#xff1a;程序中独立的功能。将反复书写的代码&#xff0c;又不确定什么时候回用到的代码打包起来。 2、函数的基本格式 函数的定义格式&#xff08;写在main函数外&#xff09; void 函数名() { 函数…...

windows中docker安装redis和redisinsight记录

创建一个Redis运行容器&#xff0c;命令如下 docker run -it -d --name redis -p 6379:6379 redis --bind 0.0.0.0 --protected-mode no -d 代表Redis容器后台运行 --name redis 给创建好的容器起名叫redis -p 6379:6379 将容器的6379端口映射到宿主机的6379端口&#xff0c;注…...

itextpdf打印A5的问题

使用A5打印的时候&#xff0c;再生成pdf是没有问题的。下面做了一个测试&#xff0c;在打印机中&#xff0c;使用A5的纸张横向放入&#xff0c;因为是家用打印机&#xff0c;A5与A4是同一个口&#xff0c;因此只能这么放。 使用itextpdf生成pdf&#xff0c;在浏览器中预览pdf是…...

qt QUndoView详解

1、概述 QUndoView 是 Qt 框架中用于显示 QUndoStack&#xff08;撤销堆栈&#xff09;内容的视图类。它通常与 QUndoStack 一起使用&#xff0c;为用户提供了一个可视化的界面来查看和操作撤销/重做历史。QUndoView 可以显示堆栈中的每个命令&#xff0c;并允许用户通过界面进…...

python+智谱AI-实现钉钉消息自动回复

python智谱AI-实现钉钉消息自动回复 实现了电脑窗口切换&#xff0c;截图识别未读消息&#xff0c;与语言模型交互后&#xff0c;将答案带入到钉钉窗口中。偷个懒&#xff0c;直接贴代码了&#xff0c;后续不断完善注释&#xff0c;如果遇到读不懂的地方&#xff0c;欢迎交流。…...

Kafka-Eagle的配置——kafka可视化界面

通过百度网盘分享的文件&#xff1a;kafka-eagle-bin-2.0.8.tar.gz 链接&#xff1a;https://pan.baidu.com/s/1H3YONkL97uXbLTPMZHrfdg?pwdsltu 提取码&#xff1a;sltu 一、界面展示 二、软件配置 1、关闭kafka集群 kf.sh stop 2、将该软件上传到/opt/modules下 cd /opt…...

【命令操作】Linux上带宽流量监控nethogs命令详解 _ 统信 _ 麒麟 _ 方德

原文链接&#xff1a;【命令操作】Linux上带宽流量监控nethogs命令详解 | 统信 | 麒麟 | 方德 Hello&#xff0c;大家好啊&#xff01;今天带来一篇关于Linux上nethogs命令详解的文章。nethogs是一款非常实用的网络流量监控工具&#xff0c;帮助用户实时查看系统中每个进程的网…...

【入门篇】数字统计——多语言版

题目跳转&#xff1a;数字统计 题目解析&#xff1a; 这道题目要求统计在给定范围 [L, R] 内所有整数中数字 2 出现的次数。例如&#xff0c;在范围 [2, 22] 中&#xff0c;数字 2 分别在数 2、12、20、21、22 中出现的次数&#xff0c;最终出现了6次。 题目的输入为两个正…...

探索那些现代C++语法糖

本文来聊聊现代C的一些语法糖。 1.Auto auto x 10; // 推导为 int auto y 3.14; // 推导为 double2.范围-based for 循环 std::vector<int> v {1, 2, 3, 4, 5}; for (auto val : v) {std::cout << val << " "; }3.nullptr int* ptr nullpt…...

多模态学习路线(2)——DL基础系列

目录 前言 一、归一化 1. Layer Normalization (LN) 2. Batch Normalization (BN) 3. Instance Normalization (IN) 4. Group Normalization (GN) 5. Root Mean Square Normalization&#xff08;RMSNorm&#xff09; 二、激活函数 1. Sigmoid激活函数&#xff08;二分类&…...

CMake系统学习笔记

CMake系统学习笔记 基础操作 最基本的案例 // code #include <iostream>int main() {std::cout << "hello world " << std::endl;return 0; }// CMakeLists.txt cmake_minimum_required(VERSION 3.0)# 定义当前工程名称 project(demo)add_execu…...

Jmeter(四) - 如何在jmeter中创建网络测试计划

1.简介 如何创建基本的 测试计划来测试网站。您将创建五个用户&#xff0c;这些用户将请求发送到JMeter网站上的两个页面。另外&#xff0c;您将告诉用户两次运行测试。 因此&#xff0c;请求总数为&#xff08;5个用户&#xff09;x&#xff08;2个请求&#xff09;x&#xff…...

Spring AOP执行原理源码解析

对【com.example.demo.TestAspect#aopTest】连接点增加了五个通知 在调用【com.example.demo.A#testAop()】&#xff08;用户自定义&#xff09;方法时&#xff0c;Cglib拦截器对其进行了拦截 可以看到执行顺序分别是环绕前置&#xff0c;前置&#xff0c;环绕后置&#xff0c;…...

kubernetes jenkins pipeline优化拉取大仓库性能指定分支+深度

有时候我们历史的git仓库&#xff0c;提交了某个比较大的文件如果不限制 depth &#xff0c;就会拉取所有的历史提交记录&#xff0c;这样在历史仓库比较大的时候 clone 非常之慢&#xff0c;而实际上我们只需要最新的代码来构建就行了&#xff0c;为了优化性能&#xff0c;我们…...

自动化办公集成工具:一站式解决文档处理难题

1. 项目概述 在当今信息化时代,办公自动化已成为提升工作效率的关键。本文将详细介绍一款基于Python和PyQt5开发的「自动化办公集成工具」,该工具集成了多种常用的办公文档处理功能,包括批量格式转换、文本智能替换、表格数据清洗等,旨在为用户提供一站式的办公自动化解决方…...

MATLAB实战:四旋翼姿态控制仿真方案

以下是一个基于MATLAB/Simulink的四旋翼姿态控制仿真方案。本方案使用简化姿态动力学模型&#xff0c;并设计PID控制器进行稳定控制。 1. 四旋翼姿态动力学模型 核心方程&#xff1a;I * ω̇ ω (I * ω) τ 其中&#xff1a; I diag([Ixx, Iyy, Izz]) 为转动惯量矩阵 …...

【HarmonyOS5】UIAbility组件生命周期详解:从创建到销毁的全景解析

⭐本期内容&#xff1a;【HarmonyOS5】UIAbility组件生命周期详解&#xff1a;从创建到销毁的全景解析 &#x1f3c6;系列专栏&#xff1a;鸿蒙HarmonyOS&#xff1a;探索未来智能生态新纪元 文章目录 前言生命周期全景图详细状态解析与最佳实践&#x1f3ac; Create状态&#…...

紫光同创FPGA系列实现Aurora 8b/10b协议

特性 1.兼容XILINX aurora IP核 2.支持X1、X2、X4、X8模式&#xff08;根据硬件条件选择模式&#xff09; 3.支持FRAMING和STREAMING 用户接口 4.自动初始化和维护链路状态 5.支持热插拔 6.支持扰码、解扰 7.支持流量控制 8.支持crc用户数据 9.支持全双工或者半双工模式 10.最…...

零基础在实践中学习网络安全-皮卡丘靶场(第十期-Over Permission 模块)

经过这么长时间的学习&#xff0c;我相信大家已经有了很大的信心&#xff0c;有可能会有看不起的意思&#xff0c;因为皮卡丘是基础靶场&#xff0c;但是俗话说"基础不牢&#xff0c;地动山摇"&#xff0c;所以还请大家静下心来进行学习 来翻译一下是什么意思&#…...