软件设计模式系列之二十四——模板方法模式

news2024/11/20 9:33:13

在软件设计领域,设计模式是一组被反复使用、多次实践验证的经典问题解决方案。其中,模板方法模式是一种行为型设计模式,用于定义一个算法的骨架,将算法中的某些步骤延迟到子类中实现,从而使子类可以重新定义算法的某些特定步骤,同时保持算法的整体结构不变。本文将深入探讨模板方法模式,包括其定义、举例、结构、实现步骤、代码实现、典型应用场景、优缺点、类似模式以及一个小结。

1 模式的定义

模板方法模式是一种行为型设计模式,它定义了一个算法的骨架,将算法的具体步骤延迟到子类中实现。这意味着,模板方法模式允许多个子类共享相同的算法框架,但可以在子类中实现各自特定的步骤,从而实现了代码的复用和扩展。通常,模板方法由一个抽象类定义,其中包含了算法的骨架,以及一些抽象方法,用于由子类来实现。

2 举例说明

在日常生活中,有许多例子符合模板方法模式的设计,这些例子都展示了一种在不同场景中重复使用相同的步骤或算法骨架的情况。以下是几个大家熟知的例子:

烹饪食物:烹饪是一个典型的模板方法模式示例。无论是制作披萨、汉堡、还是意大利面,都需要执行一系列共同的步骤,如准备食材、烹饪、装盘等。不同的食物有不同的特定步骤,可以在子类中实现。
在这里插入图片描述

咖啡店的饮料制作:就像前文提到的咖啡和茶的例子一样,咖啡店制作不同饮料也遵循相似的模板,包括烧水、冲泡、倒入杯子和加入调味品等步骤。

电子商务购物流程:在线购物网站通常具有相似的购物流程,包括浏览商品、将商品添加到购物车、填写配送信息、选择支付方式、确认订单等步骤。不同电子商务网站可以在这些步骤的执行顺序和细节上进行定制。

这些例子都展示了在日常生活中广泛存在的模板方法模式的应用,其中共享的步骤或算法骨架可以在不同的情境中重复使用,而特定的细节可以在子类或具体实例中定制。这种设计方法有助于提高效率、减少重复工作,并确保一致性。

3 结构

模板方法模式包含以下主要组成部分:
在这里插入图片描述

抽象类(Abstract Class):定义算法的骨架,包含一个或多个抽象方法,用于由子类实现。通常,抽象类还包含模板方法,该方法定义了算法的步骤顺序。

具体子类(Concrete Subclass):实现抽象类中的抽象方法,从而提供了算法的具体实现。

4 实现步骤

下面是使用模板方法模式的一般实现步骤:

创建一个抽象类,定义算法的骨架,并在其中声明抽象方法。

在抽象类中实现模板方法,该方法包含算法的步骤顺序,其中调用了抽象方法。

创建具体子类,继承自抽象类,并实现抽象方法以提供具体的算法实现。

在客户端代码中,使用具体子类来调用模板方法以执行算法。

5 代码实现

以下是一个使用Java语言实现的制作咖啡和茶的示例代码:

// 抽象类:饮料制备模板
abstract class Beverage {
    // 模板方法,制备饮料
    final void prepareBeverage() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }

    // 抽象方法:烧水
    abstract void boilWater();

    // 抽象方法:冲泡
    abstract void brew();

    // 抽象方法:倒入杯子
    abstract void pourInCup();

    // 抽象方法:加入调味品
    abstract void addCondiments();
}

// 具体子类:咖啡
class Coffee extends Beverage {
    @Override
    void boilWater() {
        System.out.println("烧水");
    }

    @Override
    void brew() {
        System.out.println("冲泡咖啡");
    }

    @Override
    void pourInCup() {
        System.out.println("倒入杯子");
    }

    @Override
    void addCondiments() {
        System.out.println("加入糖和牛奶");
    }
}

// 具体子类:茶
class Tea extends Beverage {
    @Override
    void boilWater() {
        System.out.println("烧水");
    }

    @Override
    void brew() {
        System.out.println("冲泡茶叶");
    }

    @Override
    void pourInCup() {
        System.out.println("倒入杯子");
    }

    @Override
    void addCondiments() {
        System.out.println("加入柠檬");
    }
}

public class TemplateMethodPatternExample {
    public static void main(String[] args) {
        Beverage coffee = new Coffee();
        coffee.prepareBeverage();

        Beverage tea = new Tea();
        tea.prepareBeverage();
    }
}

6 典型应用场景

模板方法模式在实际软件开发中有许多应用场景,其中一些典型的包括:

框架设计:在框架中,模板方法模式用于定义框架的核心算法,而具体的功能由子类实现。例如,Java中的Servlet就是使用了模板方法模式。

库设计:在库中,模板方法模式用于定义通用的算法,以满足不同的客户需求。客户可以通过继承库中的类并实现抽象方法来自定义功能。

游戏开发:在游戏开发中,模板方法模式可用于定义游戏中的角色行为或关卡设计,其中不同的角色或关卡可以通过继承来实现特定的行为。

7 优缺点

优点:

代码复用:模板方法模式提供了一种代码复用的方式,使得多个子类可以共享算法的核心结构,减少了重复代码的数量。

扩展性:模板方法模式允许子类扩展或修改算法的特定步骤,而不需要改变算法的整体结构。

高层控制:模板方法模式将算法的控制权交给了抽象类,使得高层模块可以更方便地控制算法的执行。

缺点:

过度抽象:如果不合理地设计抽象类和抽象方法,可能会导致过度抽象,使得代码难以理解和维护。

限制子类:模板方法模式要求子类必须按照模板方法的顺序执行算法步骤,这可能会限制子类的灵活性。

8 类似模式

与模板方法模式类似的模式包括以下几种:

策略模式(Strategy Pattern):策略模式也允许在运行时选择算法,但与模板方法模式不同,它将算法封装成独立的对象,使得客户可以在运行时切换不同的算法实现。模板方法模式通过继承来实现算法的变化,而策略模式通过组合和委托来实现。两者都涉及到将算法进行抽象,但模板方法模式更适用于定义算法的骨架,而策略模式更适用于在不同算法之间进行动态切换。

工厂方法模式(Factory Method Pattern):工厂方法模式用于创建对象,它定义一个创建对象的接口,但让子类决定实例化哪个类。虽然工厂方法模式通常不涉及算法的执行顺序,但它也可以看作是一种创建对象的模板,具有一定的相似性。两者都涉及创建对象,但工厂方法模式关注对象的创建,而模板方法模式关注定义算法的骨架。

命令模式(Command Pattern):命令模式将请求封装成对象,使得可以在不同的上下文中执行请求。虽然命令模式主要关注将请求和执行解耦,但在一些情况下,可以使用模板方法模式来定义具体的命令执行流程。两者都涉及定义执行流程,但命令模式主要用于将请求和执行解耦,而模板方法模式主要用于定义算法的骨架。

虽然这些模式有一些相似之处,但它们的主要关注点和使用方式略有不同。模板方法模式的主要目的是定义算法的骨架,允许子类定制特定的步骤,而其他模式更侧重于其他领域,如创建对象、封装请求等。因此,在选择使用哪种模式时,需要根据具体的需求和问题来决定哪种模式更适合。

9 小结

模板方法模式是一种强大的设计模式,它允许我们定义算法的骨架并延迟特定步骤的实现到子类中。通过这种方式,我们可以实现代码的复用和扩展,同时保持算法的整体结构不变。在实际应用中,模板方法模式常用于框架和库的设计,以及需要定义多个具有相似结构的算法的场景。但要谨慎使用,避免过度抽象和限制子类的问题。在正确的情况下,模板方法模式可以提高代码的可维护性和灵活性,使软件更易于扩展和维护。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1059139.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

互联网Java工程师面试题·Zookeeper 篇·第二弹

目录 13. 服务器角色 14. Zookeeper 下 Server 工作状态 15. 数据同步 16. zookeeper 是如何保证事务的顺序一致性的? 17. 分布式集群中为什么会有 Master? 18. zk 节点宕机如何处理? 19. zookeeper 负载均衡和 nginx 负载均衡区别 20…

代码随想录算法训练营第五十七天 | 392.判断子序列 115.不同的子序列

1. 判断子序列 392. 判断子序列 - 力扣(LeetCode) dp[i][j] 表示以下标i-1为结尾的字符串s,和以下标j-1为结尾的字符串t,相同子序列的长度。 class Solution {public boolean isSubsequence(String s, String t) {//dp[i][j] 表示…

Spring MVC:数据绑定

Spring MVC 数据绑定数据类型转换数据格式化数据校验 附 数据绑定 数据绑定,指 Web 页面上请求和响应的数据与 Controller 中对应处理方法上的对象绑定(即是将用户提交的表单数据绑定到 Java 对象中)。 过程如下: ServletRequest…

代数科学计算:LiveMath Maker v3.6.0 cRACK

LiveMath Maker 是一个数学计算机程序,您可以使用它来制作(并探索、实验和创建)LiveMath。您和LiveMath Maker制作的任何LiveMath都可以通过互联网与世界共享。 用LiveMath Maker 来进行数学研究,函数学习,深入探索、实验和创建你的LiveMath…

通用收藏管理器Koillection

什么是 Koillection ? Koillection 是一个自托管的收藏管理器,旨在跟踪任何类型的物理(主要)收藏,如书籍、DVD、邮票、游戏……,由于 Koillection 旨在用于任何类型的收藏,它不支持自动下载元数…

计算机网络-计算机网络体系结构-概述,模型

目录 一、计算机网络概述 二、性能指标 速率 带宽 吞吐量 时延 往返时延RTT 利用率 三、计算机网络体系结构 分层结构 IOS模型 应用层-> 表示层-> 会话层-> 传输层-> 网络层-> 数据链路层-> 物理层-> TCP/IP模型 一、计算机网络概述 计…

用向量数据库Milvus Cloud搭建检索知识库机器人

检索知识库 Milvus 中已经存储了文本块向量,现在可以进行向量查询了。 以下函数创建了 1 个查询 pipeline。注意,这是本教程中最为关键的一个步骤! ops.ann_search.osschat_milvus(host=MILVUS_HOST, port=MILVUS_PORT, **{metric_type: IP, limit: 3, output_fields: [text…

设计模式11、享元模式Flyweight

解释说明:享元模式(Flyweight Pattern)运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。 抽象享元类(Flyweight&…

STM32复习笔记(五):FSMC连接外部SRAM

目录 Preface: (一)原理相关 (二)CUBEMX配置 (三)轮询方式读写 (四)DMA方式读写 Preface: STM32F4有一个FSMC(Flexible Static Memory Contr…

【C++11新算法】all_of、any_of、none_of算法

文章目录 前言一、概念1.1all_of1.2any_of1.3none_of 二、使用方式三、示例代码3.1all_of3.2any_of3.3none_of3.4检查一个字符串中的所有字符是否为小写字母3.5查一个容器中是否至少存在一个字符串长度超过5的元素 总结 前言 在C11标准中,引入了许多重要的新特性和…

Elasticsearch安装并使用Postman访问

Elasticsearch,一个强大的开源搜索和分析引擎,已经在全球范围内被广泛应用于各种场景,包括网站搜索、日志分析、实时应用等。由于其强大的功能和灵活性,Elasticsearch 已经成为大数据处理的重要工具。然而,对于许多初次…

C#,数值计算——Ranq2的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { /// <summary> /// Backup generator if Ranq1 has too short a period and Ran is too slow.The /// period is 8.5E37. Calling conventions same as Ran, above. /// </summary> …

算法题系列10·最长公共前缀

目录 题目描述 思路 实现 题目描述 编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀&#xff0c;返回空字符串 ""。示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;&qu…

大数据Flink(九十六):DML:Deduplication

文章目录 DML:Deduplication DML:Deduplication Deduplication 定义(支持 Batch\Streaming):Deduplication 其实就是去重,也即上文介绍到的 TopN 中 row_number = 1 的场景,但是这里有一点不一样在于其排序字段一定是时间属性列,不能是其他非时间属性的普通列。在 ro…

python中实现定时任务的几种方案

目录 while True: sleep()Timeloop库threading.Timersched模块schedule模块APScheduler框架Celery框架数据流工具Apache Airflow概述Airflow 核心概念Airflow 的架构 总结以下几种方案实现定时任务&#xff0c;可根据不同需求去使用不同方案。 while True: sleep() 利用whil…

【2023年11月第四版教材】第17章《干系人管理》(合集篇)

第17章《干系人管理》&#xff08;合集篇&#xff09; 1 章节内容2 管理基础3 管理过程3.1 管理的过程★★★ &#xff08;22上44&#xff09;3.2 管理ITTO汇总★★★ 4 过程1-识别干系人4.1 数据收集★★★4.3数据分析4.4 权力利益方格4.5 数据表现&#xff1a;干系人映射分析…

【数据科学】Scikit-learn[Scikit-learn、加载数据、训练集与测试集数据、创建模型、模型拟合、拟合数据与模型、评估模型性能、模型调整]

这里写目录标题 一、Scikit-learn二、加载数据三、训练集与测试集数据四、创建模型4.1 有监督学习评估器4.1.1 线性回归4.1.2 支持向量机(SVM)4.1.3 朴素贝叶斯4.1.4 KNN 4.2 无监督学习评估器4.2.1 主成分分析(PCA)4.2.2 K Means 五、模型拟合5.1 有监督学习5.2 无监督学习 六…

全新UI彩虹外链网盘系统源码(前后端美化模板)

全新UI彩虹外链网盘系统源码前后端美化模板&#xff0c;支持所有格式文件的上传、生成文件外链、图片外链、音乐视频外链等功能&#xff0c;同时还可以自动生成相应的 UBB 代码和 HTML 代码&#xff0c;支持文本、图片、音乐、视频在线预览。这不仅仅是一个网盘&#xff0c;更是…

竞赛 机器视觉 opencv 深度学习 驾驶人脸疲劳检测系统 -python

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.2 打哈欠检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#x…

算法题系列9·最后一个单词的长度

目录 题目描述 实现 题目描述 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中最后一个单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。示例 1&#xff1a; 输入&#xff1a;s "Hello Worl…