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

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

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 {@Overridevoid boilWater() {System.out.println("烧水");}@Overridevoid brew() {System.out.println("冲泡咖啡");}@Overridevoid pourInCup() {System.out.println("倒入杯子");}@Overridevoid addCondiments() {System.out.println("加入糖和牛奶");}
}// 具体子类:茶
class Tea extends Beverage {@Overridevoid boilWater() {System.out.println("烧水");}@Overridevoid brew() {System.out.println("冲泡茶叶");}@Overridevoid pourInCup() {System.out.println("倒入杯子");}@Overridevoid 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.rhkb.cn/news/147762.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lv7 嵌入式开发-网络编程开发 03 TCP/IP与五层体系结构

目录 1 TCP/IP协议族体系结构 1.1 OSI与TCP/IP 1.2 TCP/IP 的体系结构 1.3 TCP/IP 体系结构的另一种表示方法 1.4 沙漏计时器形状的 TCP/IP 协议族 2 五层协议的体系结构 2.1 各层的主要功能 2.2 互联网中客户-服务器工作方式 2.3 同时为多个客户进程提供服务 3 练…

react 网页/app复制分享链接到剪切板,分享到国外各大社交平台,通过WhatsApp方式分享以及SMS短信方式分享链接内容

1.需求 最近在做一个国际网站app,需要把app中某个页面的图文链接分享到国外各大社交平台上(facebook,whatapp,telegram,twitter等),以及通过WhatApp聊天方式分享,和SMS短信方式分享链接内容,该怎么做呢?图示如下: 分享到国外各大社交平台&am…

Kubernetes 学习总结(38)—— Kubernetes 与云原生的联系

一、什么是云原生? 伴随着云计算的浪潮,云原生概念也应运而生,而且火得一塌糊涂,大家经常说云原生,却很少有人告诉你到底什么是云原生,云原生可以理解为“云”“原生”,Cloud 可以理解为应用程…

选择排序算法:简单但有效的排序方法

在计算机科学中,排序算法是基础且重要的主题之一。选择排序(Selection Sort)是其中一个简单但非常有用的排序算法。本文将详细介绍选择排序的原理和步骤,并提供Java语言的实现示例。 选择排序的原理 选择排序的核心思想是不断地从…

Springboot+Vue+Mysql实现模拟汽车保养系统(附源码)

前言 本项目基于springbootvue搭建的汽车保养的系统,页面较为粗糙,前端好的小伙伴可自行优化。 项目环境 -环境框架后端JDK1.8SpringBootmybatisPlus前端NodeJS16.0Vue2.0ElementPlus数据库MySQL8.0- 数据库设计 数据表备注banner轮播图表car用户汽…

C++ 程序员入门之路——旅程的起点与挑战

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…

【maven】idea中基于maven-webapp骨架创建的web.xml问题

IDEA中基于maven-webapp骨架创建的web工程&#xff0c;默认的web.xml是这样的。 <!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" ><web-app><display-name…

本地部署 Qwen-Agent

本地部署 Qwen-Agent 1. Qwen-Agent 概述2. Github 地址3. 创建虚拟环境4. 安装 flash-attention5. 部署 Qwen 模型服务6. 部署 Qwen-Agent7. 浏览器访问 Qwen Agent8. 安装浏览器助手 1. Qwen-Agent 概述 Qwen-Agent 是一个代码框架&#xff0c;用于发掘开源通义千问模型&…

2120 -- 预警系统题解

Description OiersOiers 国的预警系统是一棵树&#xff0c;树中有 &#xfffd;n 个结点&#xff0c;编号 1∼&#xfffd;1∼n&#xff0c;树中每条边的长度均为 11。预警系统中只有一个预警信号发射站&#xff0c;就是树的根结点 11 号结点&#xff0c;其它 &#xfffd;−1…

面试题:Kafka 为什么会丢消息?

文章目录 1、如何知道有消息丢失&#xff1f;2、哪些环节可能丢消息&#xff1f;3、如何确保消息不丢失&#xff1f; 引入 MQ 消息中间件最直接的目的&#xff1a;系统解耦以及流量控制&#xff08;削峰填谷&#xff09; 系统解耦&#xff1a; 上下游系统之间的通信相互依赖&a…

华硕X555YI, Win11下无法调节屏幕亮度

翻出一个旧电脑华硕X555YI&#xff0c;装Win11玩&#xff0c;已经估计到会有一些问题。 果然&#xff0c;装完之后&#xff0c;发现屏幕无法调节亮度。试了网上的一些方法&#xff0c;比如修改注册表等&#xff0c;无效。 估计是显卡比较老&#xff0c;哪里没兼容。然后用驱动…

C++项目:仿mudou库one thread one loop式并发服务器实现

目录 1.实现目标 2.HTTP服务器 3.Reactor模型 3.1分类 4.功能模块划分: 4.1SERVER模块: 4.2HTTP协议模块: 5.简单的秒级定时任务实现 5.1Linux提供给我们的定时器 5.2时间轮思想&#xff1a; 6.正则库的简单使用 7.通用类型any类型的实现 8.日志宏的实现 9.缓冲区…

【初识Linux】:常见指令(1)

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux的基础知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数…

PowerPoint如何设置密码?

PowerPoint&#xff0c;也就是PPT&#xff0c;是很多人工作中经常用的办公软件&#xff0c;而PPT和Word、Excel等一样可以设置密码保护。 PPT可以设置两种密码&#xff0c;一种是“打开密码”&#xff0c;也就是需要密码才能打开PPT&#xff1b;还有一种是设置成有密码的“只读…

22.app.js的全局数据共享

app.js中定义的全局变量适合 不修改且仅在js中使用的变量 目录 1 全局变量 2 修改全局变量 3 app.js中的变量不能直接在wxml中渲染 4 全局方法 1 全局变量 比如我现在想定义一个全局的变量something&#xff0c;直接在APP中写就行了 之后你可以在任何一个页面中&…

互联网Java工程师面试题·MyBatis 篇·第一弹

目录 1、什么是 Mybatis&#xff1f; 2、Mybaits 的优点 3、MyBatis 框架的缺点 4、MyBatis 框架适用场合 5、MyBatis 与 Hibernate 有哪些不同&#xff1f; 6、#{}和${}的区别是什么&#xff1f; 7、当实体类中的属性名和表中的字段名不一样 &#xff0c;怎么办 &#x…

HTML5 跨屏前端框架 Amaze UI

Amaze UI采用国际最前沿的“组件式开发”以及“移动优先”的设计理念&#xff0c;基于其丰富的组件&#xff0c;开发者可通过简单拼装即可快速构建出HTML5网页应用&#xff0c;上线仅半年&#xff0c;Amaze UI就成为了国内最流行的前端框架&#xff0c;目前在Github上收获Star数…

【C语言】【动态内存管理】malloc,free,calloc,realloc

1.malloc函数 void* malloc(size_t size)功能&#xff1a;向内存申请字节为 size大小的空间 使用时要包含头文件&#xff1a;<stdlib.h> 开辟成功&#xff1a;返回开辟好的空间初始地址的指针 开辟失败&#xff1a;返回空指针 NULL 使用举例&#xff1a; (malloc和free…

Java编程技巧:swagger2、knif4j集成SpringBoot或者SpringCloud项目

目录 1、springbootswagger2knif4j2、springbootswagger3knif4j3、springcloudswagger2knif4j 1、springbootswagger2knif4j 2、springbootswagger3knif4j 3、springcloudswagger2knif4j 注意点&#xff1a; Api注解&#xff1a;Controller类上的Api注解需要添加tags属性&a…

OpenGLES:绘制一个混色旋转的3D圆柱

一.概述 上一篇博文讲解了怎么绘制一个混色旋转的立方体 这一篇讲解怎么绘制一个混色旋转的圆柱 圆柱的顶点创建主要基于2D圆进行扩展&#xff0c;与立方体没有相似之处 圆柱绘制的关键点就是将圆柱拆解成&#xff1a;两个Z坐标不为0的圆 一个长方形的圆柱面 绘制2D圆的…