当前位置: 首页 > 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…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

12.找到字符串中所有字母异位词

🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

Bean 作用域有哪些?如何答出技术深度?

导语: Spring 面试绕不开 Bean 的作用域问题,这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开,结合典型面试题及实战场景,帮你厘清重点,打破模板式回答&#xff0c…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...

CppCon 2015 学习:Time Programming Fundamentals

Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...