设计模式-模板方法模式(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 带来了身份验证的未来,简化了用户登录应用程序和网站的方式,同时使其更加安全。 登录可能具有挑战性 - 密码经常使用,…...

【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…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...