【设计模式深度剖析】【1】【行为型】【模板方法模式】| 以烹饪过程为例加深理解

👈️上一篇:结构型设计模式对比

文章目录

  • 模板方法模式
  • 定义
    • 英文原话
    • 直译
    • 如何理解呢?
  • 2个角色
    • 类图
    • 代码示例
  • 应用
    • 优点
    • 缺点
    • 使用场景
  • 示例解析:以烹饪过程为例
    • 类图
    • 代码示例

模板方法模式

模板方法模式(Template Method Pattern)是一种行为型设计模式,它通过一个抽象类定义了一个操作的算法骨架,而将一些步骤延迟到子类中实现。

简而言之,模板方法模式就像是一个烹饪食谱,规定了基本的烹饪流程(算法骨架),但允许厨师根据具体食材(子类)调整某些步骤(如烹饪时间、温度等),从而制作出不同风味的菜肴

定义

英文原话

Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.

直译

定义一个操作中的算法框架,进而推迟一些步骤的执行,将其延迟到子类中。模板方法使得子类在不改变算法的结构的情况下,可以改变算法的某些特定步骤。

如何理解呢?

模板方法模式从字面上理解,可以拆分为“模板”和“方法”两个部分。

  1. 模板:指的是一种固定的框架或结构,它定义了某个过程或操作的基本流程或步骤。在模板方法模式中,这个“模板”通常由抽象类中的模板方法提供,该方法定义了一个算法的框架,即算法执行的大致步骤和顺序。
  2. 方法:指的是具体的操作或步骤。在模板方法模式中,这些“方法”通常包括抽象方法(由子类实现)和具体方法(在抽象类中实现)。抽象方法定义了算法中需要子类实现的部分,而具体方法则包含了算法中通用的、不需要子类改变的部分。

我们可以以一个简单的烹饪过程为例。假设我们有一个基本的烹饪流程,其中包含了预热烤箱、烹饪食物和关闭烤箱的步骤。但不同的食物需要不同的烹饪时间和温度,这部分就是可以定制的部分。

假设我们想要烤一个蛋糕和一个披萨。两者都需要预热烤箱,但烹饪时间和温度不同,烹饪完成后都需要关闭烤箱。这里,预热烤箱和关闭烤箱就是模板方法中固定的部分,而烹饪食物则是需要根据不同食物来定制的部分。(见下文示例解析)

2个角色

模板方法模式(Template Method Pattern)中的角色通常包括:

  1. 抽象类(Abstract Class):这个角色定义了一个或多个抽象操作,以便让子类实现。这些抽象操作是基本操作,还需要定义一个或几个模板方法,这些模板方法一般是具体的方法,定义了一个算法的框架。
  2. 具体子类(Concrete Subclasses):这是抽象模板角色的子类,它们实现抽象模板角色中的抽象方法,以完成算法中与特定子类相关的步骤。

通过使用模板方法模式,开发者可以在不改变算法结构的情况下,通过子类来重定义算法的某些特定步骤,从而实现算法的灵活性和可复用性。

类图

在这里插入图片描述

代码示例

下面是一个Java示例,展示了模板方法模式:

package com.polaris.designpattern.list3.behavioral.pattern01.templatemethod.classicdemo;// 抽象类,定义了模板方法
abstract class AbstractClass {// 模板方法,定义了算法的框架  public final void templateMethod() {specificMethod1(); // 调用第一个抽象方法  // 可能还有其他的通用操作或条件判断  specificMethod2(); // 调用第二个抽象方法  }// 抽象操作,子类必须实现  protected abstract void specificMethod1();// 另一个抽象操作,子类也必须实现  protected abstract void specificMethod2();
}// 具体子类A  
class ConcreteClassA extends AbstractClass {// 实现抽象操作  @Overrideprotected void specificMethod1() {System.out.println("ConcreteClassA.specificMethod1()");}// 实现抽象操作  @Overrideprotected void specificMethod2() {System.out.println("ConcreteClassA.specificMethod2()");}
}// 具体子类B  
class ConcreteClassB extends AbstractClass {// 实现抽象操作  @Overrideprotected void specificMethod1() {System.out.println("ConcreteClassB.specificMethod1()");}// 实现抽象操作  @Overrideprotected void specificMethod2() {System.out.println("ConcreteClassB.specificMethod2()");}
}// 客户端代码  
public class TemplateMethodTest {public static void main(String[] args) {AbstractClass classA = new ConcreteClassA();classA.templateMethod(); // 输出 ConcreteClassA.specificMethod1() 和 ConcreteClassA.specificMethod2()  AbstractClass classB = new ConcreteClassB();classB.templateMethod(); // 输出 ConcreteClassB.specificMethod1() 和 ConcreteClassB.specificMethod2()  }
}
/* Output:
ConcreteClassA.specificMethod1()
ConcreteClassA.specificMethod2()
ConcreteClassB.specificMethod1()
ConcreteClassB.specificMethod2()
*///~

在这个示例中,AbstractClass 是抽象类,它定义了一个模板方法 templateMethod(),该方法调用了两个抽象操作 specificMethod1()specificMethod2()ConcreteClassAConcreteClassB 是具体子类,它们分别实现了这两个抽象操作。客户端代码通过调用模板方法来执行算法,而具体的步骤(specificMethod1()specificMethod2())则由不同的子类实现。

模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一个操作中的算法框架,而将一些步骤延迟到子类中。这使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。

应用

模板方法模式在以下场景中特别有用:

  1. 算法复用:当多个类有相似的行为,但部分行为需要定制时,可以使用模板方法模式。
  2. 框架设计:在框架设计中,模板方法模式可以帮助实现一些可扩展的、可定制的框架。
  3. 一次性算法:如果一个算法很少改变,但其中的某些步骤可能需要根据具体情况进行定制时,可以使用模板方法模式。

优点

  1. 代码复用:模板方法模式通过把不变行为搬到超类,去除了子类中的重复代码。
  2. 扩展性好:子类可以通过实现或重写抽象方法或钩子方法来改变或扩展算法的部分行为。
  3. 灵活性高:在模板方法模式中,可以通过定义抽象方法和钩子方法来实现算法的灵活性和可扩展性。
  4. 符合开闭原则:对扩展开放,对修改关闭。在模板方法模式中,增加新的功能可以通过增加新的子类来实现,而不需要修改现有的代码。

缺点

  1. 抽象层次提高:模板方法模式会增加类的抽象层次,使得子类之间的关系更加复杂。
  2. 可能产生过多子类:如果每个不同的行为都使用子类来实现,那么类的个数可能会急剧增加。
  3. 性能考虑:由于使用了继承,如果子类过多,可能会影响系统的性能。

使用场景

  1. 创建框架:当我们需要创建一个框架,并希望这个框架具有可扩展性和可定制性时,可以使用模板方法模式。
  2. 实现回调:在某些情况下,我们可能需要让子类在特定的事件发生时执行一些操作,这时可以使用模板方法模式来实现回调。
  3. 资源初始化:当资源的初始化或清理具有固定的流程,但某些步骤可能需要根据具体情况进行定制时,可以使用模板方法模式。
  4. 算法复用:当多个类有相似的行为,但部分行为需要根据具体情况进行定制时,可以使用模板方法模式来复用代码。

模板方法模式是一种非常实用的设计模式,它可以帮助我们更好地组织代码,提高代码的可维护性和可扩展性。

示例解析:以烹饪过程为例

假设我们有一个基本的烹饪流程,其中包含了预热烤箱、烹饪食物和关闭烤箱的步骤。但不同的食物需要不同的烹饪时间和温度,这部分就是可以定制的部分。

假设我们想要烤一个蛋糕和一个披萨。两者都需要预热烤箱,但烹饪时间和温度不同,烹饪完成后都需要关闭烤箱。这里,预热烤箱和关闭烤箱就是模板方法中固定的部分,而烹饪食物则是需要根据不同食物来定制的部分。

类图

在这里插入图片描述

代码示例

package com.polaris.designpattern.list3.behavioral.pattern01.templatemethod.cookingdemo;// 抽象类,代表烹饪流程
abstract class CookingProcess {// 模板方法,定义了烹饪的整个过程  public final void cook() {preheatOven(); // 预热烤箱  cookFood();    // 烹饪食物(需要子类实现)  turnOffOven(); // 关闭烤箱  }// 预热烤箱的具体方法,不需要子类改变  protected void preheatOven() {System.out.println("Preheating oven to 350°F...");// 假设预热完成需要一些时间,这里省略等待逻辑  }// 烹饪食物的方法,需要子类实现  protected abstract void cookFood();// 关闭烤箱的具体方法,不需要子类改变  protected void turnOffOven() {System.out.println("Turning off the oven...");}
}// 蛋糕烹饪类  
class CakeCooking extends CookingProcess {// 实现烹饪食物的方法,这里是烹饪蛋糕  @Overrideprotected void cookFood() {System.out.println("Baking cake for 30 minutes...");// 假设烹饪完成需要一些时间,这里省略等待逻辑  }
}// 披萨烹饪类  
class PizzaCooking extends CookingProcess {// 实现烹饪食物的方法,这里是烹饪披萨  @Overrideprotected void cookFood() {System.out.println("Baking pizza for 15 minutes at 450°F...");// 假设烹饪完成需要一些时间,这里省略等待逻辑  }
}// 客户端代码  
public class CookingDemo {public static void main(String[] args) {CookingProcess cakeCooking = new CakeCooking();cakeCooking.cook(); // 烹饪蛋糕  System.out.println("--------------------");CookingProcess pizzaCooking = new PizzaCooking();pizzaCooking.cook(); // 烹饪披萨  }
}
/* Output:
Preheating oven to 350°F...
Baking cake for 30 minutes...
Turning off the oven...
--------------------
Preheating oven to 350°F...
Baking pizza for 15 minutes at 450°F...
Turning off the oven...
*///~

这个例子展示了模板方法模式如何帮助我们在保持烹饪流程基本框架不变的情况下,为不同的食物定制不同的烹饪步骤。

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

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

相关文章

LED驱动IC:HC2161,升压型LED恒流驱动ic,供应LED灯杯单节电池以上供电的LED灯串平板显示LED背光大功率LED照明

LED驱动IC: HC2161:升压型LED恒流驱动ic 概述:HC2161是一款高效率、高精度的升 压型大功率LED恒流驱动控制芯片。 HC2161内置高精度误差放大器,固 定关断时间控制电路,恒流驱动电路等, 特别适合大功率、多个高亮…

Kaggle平台进行Python版本降级

前言 最近在复现语音合成模型VITS,由于目前没有算力故去Kaggle白嫖运算资源。 VITS的运行环境要求如下 Cython0.29.21 librosa0.8.0 matplotlib3.3.1 numpy1.18.5 phonemizer2.2.1 scipy1.5.2 tensorboard2.3.0 torch1.6.0 torchvision0.7.0 Unidecode1.1.1截至2…

视频号小店,常见的违规条例!98%的商家必犯的违规细节!

哈喽~我是电商月月 做电商,不管哪个平台都有属于自己的规则条例,这些违规细节,一定要提前了解 所以今天,月月就给大家分享一下,做视频号小店的话,有哪些常见的违规细节 这里我们分三点讲解 一&#xff…

【分享】两种方法禁止修改Word文档

对于比较重要的Word文件,不想被随意编辑修改,可以试试以下两个方法,不清楚的小伙伴,一起来看看吧! 方法1:设置“只读方式” 我们可以给Word文档设置以“只读方式”打开,这样就算编辑修改了文档…

6月软考新通知:24下集成大概率是中级蕞简单的一门

2024下半年软考6月新通知: 一、24下软考考试时间安排: 24下半年软考报名时间:8月19日-9月15日 24下半年软考考试时间:11月9-12日 24下半年软考成绩查询:12月中(预计) 二、考情分析 24上软考…

09_JavaWeb会话

1.会话 HTTP是一种无状态协议; HTTP协议对于发送过请求或者响应都不做持久化处理具体来说就是客户端发送请求,服务器接收请求,但是服务器自身不会记录每一条请求都是由哪一个客户端发出的; 会话管理是通过Cookie和Session配合解…

【排序】插入排序,希尔排序

前面我们讲述了冒泡排序和选择排序,我们本章讲的排序方法是插入排序,插入排序是希尔排序实现的基础函数,大家一定要好好理解插入排序的逻辑,这样才能在后面学习希尔排序的时候,更容易的去理解,我们直接开始…

关于无法通过脚本启动Kafka集群的解决办法

启动Kafka集群时,需要在每台个节点上启动启动服务,比较麻烦,通过写了以下脚本来进行启停;发现能正常使用停止功能,不能正常启动Kafka; Kafka启停脚本: ## 以防不能通过shell脚本启动Kafka服务…

C盘扩容——只能删除C盘右边的磁盘对C盘进行扩展

winR弹出命令框 输入:compmgmt.msc 进入磁盘管理页面 注意:被删除盘如果有重要数据信息,请备份。 或者删除之前转移至其他盘,否则删除之后,则无法找回。 尤其是安装的软件。 规范安装目录十分重要。 将C盘右边的磁盘&a…

安防综合管理系统EasyCVR视频汇聚平台GA/T 1400协议中的关键消息交互示例

在当今的信息化时代,公共安全防范日益成为保障社会和谐稳定的关键。视频监控系统作为现代安全防范的重要手段,正不断在公安、交通、城市管理等领域发挥着越来越重要的作用。而GA/T 1400协议视图库,作为公安视频图像信息应用系统的标准&#x…

健身日记之倒立俯卧撑学习——起始日2024.6.4

文章目录 前言 自我介绍 昔日计划 新目标计划 瓶颈突破尝试 参考视频及文章 前言 有轻微健身基础,正式接触街健五大神技,立志在两年内解锁全部,将有机会的进行日常训练和目标肌群锻炼,这里向大家展示我的计划和安排&#xf…

opencv-python(五)

opencv的颜色通道中顺序是B,G,R。 图像属性 import cv2img cv2.imread(jk.jpg) print(fshape{img.shape}) print(fsize{img.size}) print(fdtype{img.dtype}) shape:图像像素的行,列,通道 size:行数 X …

YonSuite收款通,助力企业618更快收款

随着电商节日“618”的临近,各大企业纷纷摩拳擦掌,准备在这场年中大促中大展身手。然而,随着销售额的激增,收款管理问题也愈发凸显,成为制约企业快速发展的重要瓶颈。在这个关键时刻,YonSuite收款通凭借其卓…

echarts图例formatter配置添加百分比

echarts图例如何添加百分比 const pieChart async () > {const myChart echarts.init(piepic.value)const piedata await getPieData(); // 等待数据返回myChart.setOption({title: {},grid: {},tooltip: {trigger: item,},legend: {top: middle,align:left,icon: circl…

电源小白入门学习10——浪涌、防浪涌器件、浪涌保护芯片

浪涌、防浪涌器件、浪涌保护芯片 浪涌浪涌保护器件的分类与原理保险丝TVS二极管新防护电路 浪涌 浪涌,相信不少学习过电子的同学或多或少都通过这个词,但是到底什么是浪涌呢,GPT给我的答案是这样的: 浪涌,也称为瞬态…

【深度学习】【机器学习】支持向量机,网络入侵检测,KDD数据集

文章目录 环境加载数据归一化数据训练模型用测试数据集给出评估指标准确率召回率预测某个输入数据随便取一行数据加载训练好的SVM支持向量机模型并预测 全部数据和代码下载 环境 之前介绍过用深度学习做入侵检测,这篇用向量机。 环境Python3.10 requirements.txt…

【miniconda】安装miniconda

☆ 问题描述 ubuntu环境下安装miniconda ★ 解决方案 ubuntu环境下安装miniconda 下载miniconda 包 miniconda官网地址:https://docs.conda.io/en/latest/miniconda.html 清华大学镜像地址: https://mirrors.tuna.tsinghua.edu.cn/anaconda/minicon…

超级加速器链接促进会(UALink)能否打破英伟达的垄断?

近年来,人工智能(AI)技术的飞速发展催生了对高性能计算和数据中心互联技术的巨大需求。然而,随着市场的集中化,英伟达凭借其专有的NVLink和InfiniBand技术,几乎垄断了这一市场。这种局面引起了其他科技巨头…

MFC实现子控件focus焦点上下移动父控件ListView和Gridview也跟着向上下移动

项目中要实现mfc功能,然后子空间焦点下移,LIstView和Gridview父空间不会下移,所以就有这个文章。废话不多说直接上代码。 MFCGridView.java import android.content.Context; import android.util.AttributeSet; import android.view.View;…

白酒:产地的酿酒历史与文化遗产

云仓酒庄豪迈白酒作为中国酿酒工艺的品牌之一,其产地的酿酒历史与文化遗产具有深远的意义和价值。产地酿酒历史悠久,代代相传的酿酒技艺和与众不同的文化传统,构成了云仓酒庄豪迈白酒与众不同的品质和风味。 据云仓酒庄豪迈介绍,中…