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

news2024/11/19 5:43:03

👈️上一篇:结构型设计模式对比    |   下一篇:命令模式👉️

设计模式-专栏👈️

文章目录

  • 模板方法模式
  • 定义
    • 英文原话
    • 直译
    • 如何理解呢?
  • 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...
*///~

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


👈️上一篇:结构型设计模式对比    |   下一篇:命令模式👉️

设计模式-专栏👈️

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

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

相关文章

国自然基金的检索

(1)网址 跳转国自然基金网址:https://www.nsfc.gov.cn/ (2)查询入口 (3)进行查询

贪心算法-数组跳跃游戏(mid)

目录 一、问题描述 二、解题思路 1.回溯法 2.贪心算法 三、代码实现 1.回溯法实现 2.贪心算法实现 四、刷题链接 一、问题描述 二、解题思路 1.回溯法 使用递归的方式,找到所有可能的走步方式,并记录递归深度(也就是走步次数&#x…

fastadmin/thinkPHPQueue消息队列详细教程

thinkphp-queue 是thinkphp 官方提供的一个消息队列服务,它支持消息队列的一些基本特性: 消息的发布,获取,执行,删除,重发,失败处理,延迟执行,超时控制等队列的多队列, 内存限制 ,启动,停止,守护等消息队列可降级为同步执行1、通过composer安装thinkPHP消息队列 …

实验笔记之——DPVO(Deep Patch Visual Odometry)

本博文记录本文测试DPVO的过程,本博文仅供本人学习记录用~ 《Deep Patch Visual Odometry》 代码链接:GitHub - princeton-vl/DPVO: Deep Patch Visual Odometry 目录 配置过程 测试记录 参考资料 配置过程 首先下载代码以及创建conda环境 git clo…

大漠插件7.2422

工具名称:大漠插件7.2422 /更新时间2024年6月2日 / v7.2422 1. 综合工具的图像编辑工具可以缩放窗口了 2. 增加AiFindPic AiFindPicEx AiFindPicMem AiFindPicMemEx AiEnableFindPicWindow 共5个接口 / 工具简介: 大漠 综合 插件 (dm.dll)采用vc6.0编写,识别速度超级…

网络编程: reactor模式的步步探索与实现

网络编程: reactor模式的步步探索与实现 一.步步探索1.先看一下之前的BUG的影响2.解决拼接式读取问题3.进一步的探索4.Connection的提出5.EpollServer的修改并将监听套接字添加进去6.小演示 二.协议与业务登场1.协议,业务,解决粘包,序列反序列化等等的函数模块实现2.读写异常事…

推荐使用优豆云免费云服务器、免费虚拟主机

官网地址:https://www.udouyun.com 经济实惠:相较于其他云服务器提供商,优豆云服务器提供免费的云服务,对于一些预算有限的个人和初创企业来说,是一个不错的选择。操作便捷:优豆云服务器提供了Linux和Wind…

智能视频监控平台LntonCVS视频融合共享平台保障露营安全解决方案

在当今社会,都市生活的快节奏和压力使得越来越多的人渴望逃离城市的喧嚣,寻求一种短暂的慢生活体验。他们向往在壮丽的山河之间或宁静的乡村中露营,享受大自然的宁静与美好。随着露营活动的普及,露营地的场景也变得更加丰富多样&a…

YOLOv8---seg实例分割(制作数据集,训练模型,预测结果)

YOLOv8----seg实例分割(制作数据集,训练模型,预测结果) 内容如下:【需要软件及工具:pycharm、labelme、anaconda、云主机(跑训练)】 1.制作自己的数据集 2.在yolo的预训练模型的基础…

【scau大数据技术与原理2】综合性实验Spark集群的安装和使用——安装启动spark shell篇

实验内容简介: Spark是一个分布式计算框架,常用于大数据处理。本次实验中,首先设计一个包含主节点和从节点的Spark集群架构,并在CentOS的Linux环境下进行搭建。通过下载并解压Spark安装包,配置环境变量和集群参数&…

问题:学生品德不良的矫正与教育可以采取以下措施()。 #其他#学习方法#微信

问题:学生品德不良的矫正与教育可以采取以下措施()。 A、创设良好的交流环境,消除情绪障碍 B、提高道德认识,消除意义障碍 C、锻炼学生与诱因作斗争的意志力 D、消除习惯惰性障碍 E、发现积极因素,多方法协同进行,促进转化 参考答案如图所示

BPMN开始事件-Activiti7从入门到专家(7)

开始事件类型 bpmn开始事件表示流程的开始,定义流程如何启动,在某种情况下启动,比如接收事件启动,指定事件启动等,开始事件有5种类型: 空开始事件定时器开始事件信号开始事件消息开始事件错误开始事件 继…

Java | Leetcode Java题解之第128题最长连续序列

题目&#xff1a; 题解&#xff1a; class Solution {public int longestConsecutive(int[] nums) {Set<Integer> num_set new HashSet<Integer>();for (int num : nums) {num_set.add(num);}int longestStreak 0;for (int num : num_set) {if (!num_set.contai…

90后机器人创业者再获10亿元融资,为精密传动行业注入新动力!

据了解&#xff0c;一位90后机器人创业者再次获得近10亿元人民币的融资&#xff0c;这一消息在精密传动行业引起了广泛关注。 杭州宇树科技有限公司&#xff08;简称“宇树”&#xff09;&#xff0c;2024年春节前完成了B2轮融资&#xff0c;融资近10亿元人民币&#xff0c;本轮…

立创·天空星开发板-GD32F407VE-EXTI

本文以 立创天空星开发板-GD32F407VET6-青春版 作为学习的板子&#xff0c;记录学习笔记。 立创天空星开发板-GD32F407VE-EXTI 中断硬件触发中断示例软件触发中断示例 中断 中断分为内部中断和外部中断 外部中断是由外部设备&#xff08;如按键、传感器、通信接口等&#xff09…

【FAS】《CN103106397B》

原文 CN103106397B-基于亮瞳效应的人脸活体检测方法-授权-2013.01.19 华南理工大学 方法 / 点评 核心方法用的是传统的形态学和模板匹配&#xff0c;亮点是双红外发射器做差分 差分&#xff1a;所述FPGA芯片控制两组红外光源&#xff08;一近一远&#xff09;交替亮灭&…

硬件IIC和软件IIC的比较

&#xff08;一&#xff09;硬件IIC 硬件IIC是由STM32内部的硬件模块实现的&#xff0c;使用CPU的时钟信号来控制数据传输和时序&#xff0c;通信速度较快&#xff0c;可以达到几十MHz的速度。硬件IIC的实现相对简单&#xff0c;无需编写复杂的代码&#xff0c;因此在实现IIC通…

python的plt.axis()、plt.xlim() 和 plt.ylim()函数

坐标轴相关设置1、plt.axis():坐标轴设置 函数 plt.axis(*v, **kwargs) 主要用于设置坐标轴的属性,返回值为当前的坐标轴范围 [xmin, xmax, ymin, ymax],几种调用方式如下: 调用方式 说明 axis() 返回当前的坐标轴范围 [xmin, xmax, ymi…

空间搜索geohash概述

概述 通常在一些2C业务场景中会根据用户的位置来搜索一些内容。通常提供位置搜索的都是直接通过redis/mongodb/es等中间件实现的。 但是这些中间件又是怎么实现位置搜索的呢&#xff1b; 查了一番资料&#xff0c;发现背后一个公共的算法Geohash。 Geohash 经度和纬度是2个…

操盘手专栏 | 0-1搞懂TikTok广告优化该怎么玩!

如果你正想要或计划投放TikTok广告来提高杠杆效益&#xff0c;是否有面临下面的难题&#xff1a; 难找到系统的TikTok投放知识&#xff1f; 不懂得如何制定广告计划&#xff1f; 投放效果怎样才算有效优化&#xff1f; ...... 为此&#xff0c;超店有数邀请到了拥有8年营销…