【设计模式深度剖析】【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 {
    // 实现抽象操作  
    @Override
    protected void specificMethod1() {
        System.out.println("ConcreteClassA.specificMethod1()");
    }

    // 实现抽象操作  
    @Override
    protected void specificMethod2() {
        System.out.println("ConcreteClassA.specificMethod2()");
    }
}

// 具体子类B  
class ConcreteClassB extends AbstractClass {
    // 实现抽象操作  
    @Override
    protected void specificMethod1() {
        System.out.println("ConcreteClassB.specificMethod1()");
    }

    // 实现抽象操作  
    @Override
    protected 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 {

    // 实现烹饪食物的方法,这里是烹饪蛋糕  
    @Override
    protected void cookFood() {
        System.out.println("Baking cake for 30 minutes...");
        // 假设烹饪完成需要一些时间,这里省略等待逻辑  
    }
}

// 披萨烹饪类  
class PizzaCooking extends CookingProcess {

    // 实现烹饪食物的方法,这里是烹饪披萨  
    @Override
    protected 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...
*///~

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

生信分析进阶4 - 比对结果的FLAG和CIGAR信息含义与BAM文件指定区域提取

BAM文件时存储比对数据的常用格式,可用于短reads和长reads数据。BAM是二进制压缩格式,SAM文件为其纯文本格式,CRAM为BAM的高压缩格式,IO效率相比于BAM略差,但是占用存储空间更小。 1. BAM文件的比对信息 BAM的核心信…

软件测试期末复习

第四章 边界黑盒测试续 4.3边界值设计方法 1.边界值设计方法:故障往往出现在定义域或边界值上。通常边界值分析法是作为对等价类划分法的补充。其测试用例来自等价类的边界。是对输入或输出的边界值进行测试的一种黑盒测试方法。 2.边界值分析法和等价类划分法的…

在Visual Studio2022中同一个项目里写作业,有多个cpp文件会报错

为了省事,在同一个项目里写很多个题目,结果只有一个cpp文件时没出错,写了2个cpp文件再想运行时就出错了; 将不相关的cpp文件移出去 在源文件中对其点击右键,找到“从项目中排除”; 结果如图,剩…

网络原理-三

一、连接管理 建立连接,断开连接 建立连接,TCP有连接的. 客户端执行 socket new Socket(SeverIP,severPort); -> 这个操作就是在建立连接. 上述只是调用socket api,真正建立连接的过程,实在操作系统内核完成的. 内核是怎样完成上述的 " 建立连接 "过程的…

云硬盘的基准性能测试场景

参考来源: 深入浅出云计算-05 | 云硬盘:云上IO到底给不给力 云硬盘的性能等级 当下的云硬盘经过了多次的软硬件迭代,尤其是SSD的迅速发展,吞吐量和随机读写能力等各项性能指标都已经不再是问题了。在现代云计算中,已…

数仓建模—ChatETL

数仓建模—ChatETL 前面我们介绍过ChatBI ,就是让用户通过自然语言对话的方式可以获取到自己想要的数据,然后通过合适的报表展示出来,其实我们可以将其理解为应用层面的技术创新,但是这个实现的前提就是我们底层已经有加工好的大量的数据模型数据表,并且有完善的元数据建…

“论SOA在企业集成架构设计中的应用”必过模板,突击2024软考高项论文

考题部分 企业应用集成(Enterprise Application Integration, EAI)是每个企业都必须要面对的实际问题。面向服务的企业应用集成是一种基于面向服务体系结构(Service-OrientedArchitecture,SOA)的新型企业应用集成技术,强调将企业和组织内部的资源和业务功…

【自动化运维】不要相信人,把所有的东西都交给机器去处理

不积跬步,无以至千里;不积小流,无以成江海。 大家好,我是闲鹤,十多年开发、架构经验,先后在华为、迅雷服役过,也在高校从事教学3年;目前已创业了7年多,主要从事物联网/车…

【网络安全的神秘世界】MySQL

🌝博客主页:泥菩萨 💖专栏:Linux探索之旅 | 网络安全的神秘世界 | 专接本 MySQL MySQL 教程 | 菜鸟教程 (runoob.com) 什么是数据库 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库 在do…

COLING 2024: 复旦发布AoR,层级聚合推理突破大模型复杂推理上限

“三个臭皮匠,顶个诸葛亮?” “一个模型不行,那就再堆一个?” 过去当我们在处理复杂任务的时候,往往会考虑集成策略(Ensembling Strategy),通过多个模型投票的方式,选出…

[手游] Florence逝去的爱弗洛伦斯

图片处理工具箱Hummingbird : Hummingbird使用智能压缩技术来减少文件的大小,支持:jpg、png、webp、svg、gif、gif、css、js、html、mp4、mov,可以设置压缩的同时等比例缩放图片或视频的尺寸。可以拖放文件夹压缩,一次最多可处理1…

茉莉香飘,奶茶丝滑——周末悠闲时光的绝佳伴侣

周末的时光总是格外珍贵,忙碌了一周的我们,终于迎来了难得的闲暇。这时,打开喜欢的综艺,窝在舒适的沙发里,再冲泡一杯香飘飘茉莉味奶茶,一边沉浸在剧情的海洋中,一边品味着香浓丝滑的奶茶&#…

短视频矩阵营销系统V2.3.0

抖音矩阵云混剪系统 源码短视频矩阵营销系统V2.3.0(免授权版)(感觉和上一个版本没什么区别)多平台多账号一站式管理,一键发布作品。智能标题,关键词优化,排名查询,混剪生成原创视频&…

《异常检测——从经典算法到深度学习》29 EasyTSAD: 用于时间序列异常检测模型的工业级基准

《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: …

p2p文件传输小工具

使用webRTC的相关技术栈可以很轻松的开发一个p2p文件传输工具,这里主要讲下使用datachannel开发的一个文件传输工具client程序的使用 客户端A:需要可以访问公网,运行client的主机 客户端B:可以访问公网,可以和客户端…

go微服务项目“商城项目实战开发”整理第一部环境的准备

文章目录 商城项目实战开发环境的准备01、微服务的简单概述02、为什么要用微服务?03、本次课程微服务的技术栈04、微服务的准备工作05、微服务项目的搭建和目录的划分06、微服务项目实战 - 用户服务-srv的搭建07、微服务项目实战 - 用户服务-api的搭建08、微服务项目实战 - 商…

深度神经网络——什么是梯度提升?

在数据科学竞赛中,梯度提升模型(Gradient Boosting)是一种非常强大的工具,它能够将多个弱学习模型组合起来,形成一个强学习模型。这个过程是通过逐步添加弱学习者来实现的,每个新加入的弱学习者都专注于当前…

sudo命令的隐患-要注意安全使用!!严格管理!!严格控制

前言 众所周知,sudo命令非常方便,而且有一定的优点。比如不需要知道root密码就可以执行一些root的命令。相比于su 必须知道root密码来说,减少了root密码泄露的风险。 但是sudo也是一把非常锋利的双刃剑,需要加以限制,…

Python 关于字符串格式化

在Python中,字符串格式化有以下几种方法: 1.可以使用字符串的str.center(width), str.ljust(width), 和 str.rjust(width)方法来实现字符串的居中、左对齐和右对齐操作。 居中对齐: text "Python" centered_text text.center(10…

最新扣子(Coze)实战教程:如何创建扣子插件,完全免费,快来学习吧~

🧙‍♂️ 诸位好,吾乃斜杠君,编程界之翘楚,代码之大师。算法如流水,逻辑如棋局。 📜 本教程是《AI应用开发系列教程之扣子(Coze)实战教程》,完全免费学习。 ⭐ 关注斜杠君,可获取完整…