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

设计模式-模板方法模式(Template Method)

设计模式-模板方法模式(Template Method)

    • 一、模板方法模式概述
      • 1.1 什么是模板方法模式
      • 1.2 简单实现模板方法模式
      • 1.3 使用模板方法模式的注意事项
    • 二、模板方法模式的用途
    • 三、模板方法模式实现方式
      • 3.1 抽象类中定义模板方法,子类实现具体方法。
      • 3.2 抽象类中定义模板方法,子类实现部分方法,父类提供默认实现。
      • 3.3 抽象类中定义多个模板方法,每个模板方法对应不同的算法流程。
      • 3.4 抽象类中定义带参数的模板方法,子类根据参数选择不同的算法流程。

一、模板方法模式概述

1.1 什么是模板方法模式

模板方法模式,也被称为模板模式,是一种行为型设计模式。它在一个抽象类中公开定义了执行其方法的模板,规定了算法的骨架。其主要特点是将一些步骤延迟到子类中,这些子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

这种类型的设计模式主要解决了一些通用的方法在每一个子类都重新写了这一问题,其主要目的是将这些通用算法抽象出来。通过使用模板方法模式,子类可以在不改变算法结构的情况下,重新定义算法中的某些特定步骤。

例如,在建筑行业中,造房子的地基、走线、水管等步骤都是一样的,只有在建筑的后期才会有加壁橱加栅栏等差异。在这种情况下,可以使用模板方法模式来规划和设计建筑流程。另一个例子是西游记中的81难,这就是一个典型的顶层逻辑骨架。

1.2 简单实现模板方法模式

首先,创建一个抽象类AbstractClass,其中包含一个抽象方法templateMethod(),这个方法包含了算法的骨架。然后,创建两个子类ConcreteClassA和ConcreteClassB,分别实现了templateMethod()方法。

// 抽象类
public abstract class AbstractClass {// 抽象方法,包含算法的骨架public final void templateMethod() {step1();step2();step3();}// 具体步骤1protected abstract void step1();// 具体步骤2protected abstract void step2();// 具体步骤3protected abstract void step3();
}// 子类A
public class ConcreteClassA extends AbstractClass {@Overrideprotected void step1() {System.out.println("子类A执行步骤1");}@Overrideprotected void step2() {System.out.println("子类A执行步骤2");}@Overrideprotected void step3() {System.out.println("子类A执行步骤3");}
}// 子类B
public class ConcreteClassB extends AbstractClass {@Overrideprotected void step1() {System.out.println("子类B执行步骤1");}@Overrideprotected void step2() {System.out.println("子类B执行步骤2");}@Overrideprotected void step3() {System.out.println("子类B执行步骤3");}
}

最后,在客户端代码中,可以创建不同的子类对象,并调用它们的templateMethod()方法来执行算法

public class Client {public static void main(String[] args) {AbstractClass concreteClassA = new ConcreteClassA();concreteClassA.templateMethod();AbstractClass concreteClassB = new ConcreteClassB();concreteClassB.templateMethod();}
}

运行客户端代码,可以看到输出结果如下:

子类A执行步骤1
子类A执行步骤2
子类A执行步骤3
子类B执行步骤1
子类B执行步骤2
子类B执行步骤3

1.3 使用模板方法模式的注意事项

  • 1、抽象类应该定义算法的骨架,将一些步骤延迟到子类中实现。这些步骤应该是通用的,可以被不同的子类重写。

  • 2、抽象类中的抽象方法需要声明为final,防止被子类修改。

  • 3、抽象类可以包含一些具体的方法,这些方法可以在子类中被覆盖或直接调用。

  • 4、子类需要实现抽象类中的所有抽象方法,否则子类也必须声明为抽象类。

  • 5、客户端代码应该针对抽象类进行编程,而不是针对具体的子类。这样可以提高代码的可扩展性和可维护性。

  • 6、在模板方法模式中,子类可以根据需要对算法的某些特定步骤进行修改,但是整个算法的结构不应该被改变。

  • 7、模板方法模式适用于那些算法结构相对稳定,但某些步骤需要根据具体情况进行变化的场景。如果算法结构经常发生变化,那么使用策略模式可能更加合适。

二、模板方法模式的用途

模板方法模式,也被称为模板模式(Template Pattern),是一种行为型设计模式。它在一个抽象类中公开定义了执行其方法的模板,规定了算法的骨架。其主要特点是将一些步骤延迟到子类中实现,这些步骤可以是通用的,可以被不同的子类重写。

在Java编程语言中,模板方法模式被广泛应用。例如,在Servlet中,有一种叫做"processRequest"的方法,这个方法就是一个模板方法,定义了一系列的流程,如获取请求参数、调用service方法处理业务逻辑、返回响应结果等。具体的业务逻辑处理则由子类去实现。

此外,模板方法模式还常用于创建复杂的对象。比如在创建一个复杂的汽车对象时,这个汽车有很多部件和功能,有些部件和功能的创建和装配过程是相似的,而有些则是独特的。在这种情况下,就可以使用模板方法模式来定义一个汽车对象的创建和装配过程的骨架,然后让子类去实现具体的创建和装配过程。

总的来说,模板方法模式的优点在于提高代码复用性,增加扩展性,并且符合开闭原则。

三、模板方法模式实现方式

3.1 抽象类中定义模板方法,子类实现具体方法。

这是最常见的实现方式,也是最简单的实现方式。

// 定义一个抽象类
public abstract class Animal {// 定义一个模板方法public void makeSound() {// 默认实现System.out.println("动物发出声音");}
}// 定义一个子类,实现抽象类中的模板方法
public class Dog extends Animal {@Overridepublic void makeSound() {// 具体实现System.out.println("汪汪汪");}
}// 定义一个子类,实现抽象类中的模板方法
public class Cat extends Animal {@Overridepublic void makeSound() {// 具体实现System.out.println("喵喵喵");}
}// 测试代码
public class Main {public static void main(String[] args) {Animal dog = new Dog();dog.makeSound(); // 输出:汪汪汪Animal cat = new Cat();cat.makeSound(); // 输出:喵喵喵}
}

3.2 抽象类中定义模板方法,子类实现部分方法,父类提供默认实现。

这种方式可以使得子类更加灵活,可以根据需要选择是否覆盖父类的方法。
要实现抽象类中定义模板方法,子类实现部分方法,父类提供默认实现,可以按照以下步骤进行:

创建一个抽象类,包含一个抽象方法作为模板方法。
在抽象类中定义一个或多个默认实现的方法。
创建子类,继承抽象类,并实现抽象方法。
在子类中覆盖父类的默认实现方法。
以下是一个简单的示例:

// 抽象类
public abstract class Animal {// 模板方法public void makeSound() {System.out.println("动物发出声音");}// 默认实现方法public void eat() {System.out.println("动物吃东西");}
}// 子类
public class Dog extends Animal {// 实现抽象方法@Overridepublic void makeSound() {System.out.println("汪汪汪");}// 覆盖父类的默认实现方法@Overridepublic void eat() {System.out.println("狗狗吃骨头");}
}// 测试代码
public class Main {public static void main(String[] args) {Animal dog = new Dog();dog.makeSound(); // 输出:汪汪汪dog.eat(); // 输出:狗狗吃骨头}
}

3.3 抽象类中定义多个模板方法,每个模板方法对应不同的算法流程。

这种方式适用于有多种算法流程的场景,可以提高代码的可读性和可维护性。
要实现抽象类中定义带参数的模板方法,子类根据参数选择不同的算法流程,可以按照以下步骤进行:

  • 1、创建一个抽象类,包含一个带有参数的抽象方法作为模板方法。
  • 2、在抽象类中定义一个或多个默认实现的方法。
  • 3、创建子类,继承抽象类,并实现抽象方法。
  • 4、在子类的实现方法中,根据传入的参数选择不同的算法流程。
    以下是一个简单的示例:
// 抽象类
public abstract class AbstractClass {// 带参数的抽象方法作为模板方法public abstract void templateMethod(int param);// 默认实现的方法public void defaultMethod() {System.out.println("这是默认实现的方法");}
}// 子类
public class SubClass extends AbstractClass {// 实现抽象方法@Overridepublic void templateMethod(int param) {if (param > 0) {algorithmA();} else {algorithmB();}}// 根据参数选择不同的算法流程private void algorithmA() {System.out.println("执行算法A");}private void algorithmB() {System.out.println("执行算法B");}
}// 测试代码
public class Main {public static void main(String[] args) {SubClass subClass = new SubClass();subClass.templateMethod(1); // 输出:执行算法AsubClass.templateMethod(-1); // 输出:执行算法BsubClass.defaultMethod(); // 输出:这是默认实现的方法}
}

3.4 抽象类中定义带参数的模板方法,子类根据参数选择不同的算法流程。

这种方式适用于算法流程比较复杂的场景,可以提高代码的灵活性和扩展性。
要实现抽象类中定义带参数的模板方法,子类根据参数选择不同的算法流程,可以按照以下步骤进行:

  • 1、创建一个抽象类,包含一个带有参数的抽象方法作为模板方法。
  • 2、在抽象类中定义一个或多个默认实现的方法。
  • 3、创建子类,继承抽象类,并实现抽象方法。
  • 4、在子类的实现方法中,根据传入的参数选择不同的算法流程。
    以下是一个简单的示例:
// 抽象类
public abstract class AbstractClass {// 带参数的抽象方法作为模板方法public abstract void templateMethod(int param);// 默认实现的方法protected void defaultMethod() {System.out.println("这是默认实现的方法");}
}// 子类
public class SubClass extends AbstractClass {@Overridepublic void templateMethod(int param) {if (param > 0) {algorithmA();} else {algorithmB();}}private void algorithmA() {System.out.println("执行算法A");}private void algorithmB() {System.out.println("执行算法B");}
}// 测试代码
public class Main {public static void main(String[] args) {SubClass subClass = new SubClass();subClass.templateMethod(1); // 输出:执行算法AsubClass.templateMethod(-1); // 输出:执行算法B}
}

相关文章:

设计模式-模板方法模式(Template Method)

设计模式-模板方法模式(Template Method) 一、模板方法模式概述1.1 什么是模板方法模式1.2 简单实现模板方法模式1.3 使用模板方法模式的注意事项 二、模板方法模式的用途三、模板方法模式实现方式3.1 抽象类中定义模板方法,子类实现具体方法…...

远程登录Linux方法(Linux平台相互远程;Windows远程登录Linux、远程编码、文件传输;无法远程登录的问题解决;c程序的编译)

在实际使用Linux系统过程中我们不可避免的需要远程登录Linux,这是因为未来大家使用Linux服务器的时候你所对应的那台Linux服务器不一定提供界面(服务器可能在外地)。本篇将会介绍远程登录Linux的方法。 文章目录 1. SSH介绍2. Linux平台相互远程及文件传输2.1 Linux…...

macOS 13.6 及后续系统安装 Asahi Linux 将破坏引导

导读Asahi Linux 是一个致力于为 Apple Silicon 设备带来 Linux 支持的项目,日前有用户反馈称,若在相关设备上安装了 macOS 13.6-14,再安装 Asahi Linux ,就会导致系统引导失败,出现“黑屏”情况。 目前 Asahi Linux 项…...

Python武器库开发-flask篇之flask框架的安装(二十一)

Flask介绍 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进…...

【CASS精品教程】打开cass提示base.dcl未找到文件的解决办法

打开cass 7.1时提示base.dcl未找到文件的解决办法。 文章目录 一、问题描述二、解决办法 一、问题描述 系统上安装了cad2006cass7.1,cass软件可以正常打开,但是在使用屏幕菜单绘制地图时,选择一个工具,提示base.dcl未找到文件&am…...

[vim]Python编写插件学习笔记3 - 命令行参数

0 环境 Windows 11 22H2gVim82 (D:/ProgramFiles/Vim)Python311 (D:/ProgramFiles/Python311)Vundle v0.10.2 阅读本文前,需要先了解前文: 《[vim]Python 编写插件学习笔记1 - 开始》 《[vim]Python 编写插件学习笔记2 - 分离》 1 前提说明 由于本…...

【仙逆】王林400年晋升元婴,复仇藤化元杀尽藤姓,高老畏罪自裁

Hello,小伙伴们,我是小郑继续为大家深度解析国漫资讯。 深度爆料仙逆第10集剧情解析,高启明,缥缈宗的元婴初期老祖,一生潜心研究推演之术,洞察先机,乃是宗门之人的精神支柱。藤化元曾为寻找王林父母所在之…...

云原生实战课大纲

1. 云原生是什么 原生应用(java,pyrhon) 上云的过程应用上云遇到的问题1.微服务的拆分 微服务的访问关系应用的架构云原生适合什么样的人去学具备什么样的前提条件云原生要学习什么docker k8s devlops server mesh jks k8s监控吧自己的微服务部署上…...

数据湖架构

数据湖架构介绍 数据湖(Data Lake)是一个存储大量结构化和非结构化数据的集中式数据存储库。 与传统的数据仓库不同,数据湖采用扁平化结构,将数据存储在原始形式下,不需要进行预处理或转化。这使得数据湖能够同时支持…...

Zabbix 5.0部署(centos7+server+MySQL+Apache)

环境 系统IPZABBIX版本主机名centos7192.168.231.2195.0zabbix-server 安装zabbix 我选择版本是zabbix-5.0 zabbix的官网是Zabbix :: The Enterprise-Class Open Source Network Monitoring Solution 安装Zabbix软件源 rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/…...

YOLO改进系列之注意力机制(CloAttention模型介绍)

CloAttention来自清华大学的团队提出的一篇论文CloFormer,作者从频域编码的角度认为现有的轻量级视觉Transformer中,大多数方法都只关注设计稀疏注意力,来有效地处理低频全局信息,而使用相对简单的方法处理高频局部信息。很少有方…...

openssl+AES开发实例(linux)

文章目录 一、AES介绍二、AES原理三、AES开发实例 一、AES介绍 AES(Advanced Encryption Standard)是一种对称密钥加密标准,它是一种对称加密算法,意味着相同的密钥用于加密和解密数据。AES 是 NIST(美国国家标准与技…...

FreeRTOS源码阅读笔记3--queue.c

消息队列可以应用于发送不定长消息的场合,包括任务与任务间的消息交换,队列是 FreeRTOS 主要的任务间通讯方式,可以在任务与任务间、中断和任务间传送信息,发送到 队列的消息是通过拷贝方式实现的,这意味着队列存储…...

云原生Kubernetes系列 | 通过容器互联搭建wordpress博客系统

云原生Kubernetes系列 | 通过容器互联搭建wordpress博客系统 通过容器互联搭建一个wordpress博客系统。wordpress系统是需要连接到数据库上的,所以wordpress和mysql的镜像都是需要的。wordpress在创建过程中需要指定一些参数。创建mysql容器时需要把mysql的数据保存在宿主机本…...

java读取OPC DA数据---Utgard

java读取OPC DA数据—Utgard Utgard库已经过时,原作者早已删除库,建议使用OPC UA,兼容OPC DA。 下面讲解Utgard使用 C#和C都不用配置DCOM,直接调用函数 既然是非要用Java,那就别想太方便,需要配置DCOM(后…...

在 Android 上简单安全地登录——使用凭证管理器和密钥

我踏马很高兴地听说, Credential Manager的公开版本将于 11 月 1 日开始提供。Credential Manager 为 Android 带来了身份验证的未来,简化了用户登录应用程序和网站的方式,同时使其更加安全。 登录可能具有挑战性 - 密码经常使用&#xff0c…...

【Python】上市公司数据进行经典OLS回归实操

一、题目二、数据合并、清洗、描述性统计1、数据获取2、数据合并3、选择董监高薪酬作为解释变量的理论逻辑分析 三、多元回归模型的参数估计、结果展示与分析1、描述性统计分析2、剔除金融类上市公司3、对所有变量进行1%缩尾处理4、0-1标准化,所有解释变量5、绘制热…...

科研学习|科研软件——有序多分类Logistic回归的SPSS教程!

一、问题与数据 研究者想调查人们对“本国税收过高”的赞同程度:Strongly Disagree——非常不同意,用“0”表示;Disagree——不同意,用“1”表示;Agree--同意,用“2”表示;Strongly Agree--非常…...

微服务简单理解与快速搭建

分布式和微服务 含义 微服务架构 微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并且可通过全自动部署机制独立部署。这些服…...

QColorDialog开发实例

文章目录 一、QColorDialog基本用法:二、QColorDialog详解三、QColorDialog接口说明静态函数成员函数 四、QColorDialog代码开发实例 QColorDialog 是 Qt 框架中用于选择颜色的对话框类。它提供了一个用户友好的界面,允许用户选择颜色。以下是 QColorDi…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...