当前位置: 首页 > news >正文

【设计模式深度剖析】【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...
*///~

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

相关文章:

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

👈️上一篇:结构型设计模式对比 文章目录 模板方法模式定义英文原话直译如何理解呢? 2个角色类图代码示例 应用优点缺点使用场景 示例解析:以烹饪过程为例类图代码示例 模板方法模式 模板方法模式(Template Method Pattern&…...

JAVA:异步任务处理类CompletableFuture让性能提升一倍

一、前言 CompletableFuture 是 Java 8 引入的一个功能强大的类,用于异步编程。它表示一个可能尚未完成的计算的结果,你可以对其添加回调函数来在计算完成时执行某些操作。在 Spring Boot 应用中,CompletableFuture 可以用于提高应用的响应性…...

10Linux 进程管理学习笔记

Linux 进程管理 目录 文章目录 Linux 进程管理一.进程1.显示当前进程状态(ps)进程树(pstree)1.1实时显示进程信息(top)顶部概览信息:CPU 状态:内存状态:进程信息表头:进程列表:1.2(htop) 2.终止进程(kill)2.1通过名称…...

一些关于深度聚类以及部分对比学习的论文阅读笔记

目录 资料SwAV问题方法方法的创新点为什么有效有什么可以借鉴的地方聚类Multi-crop 代码 PCL代码 Feature Alignment and Uniformity for Test Time Adaptation代码 SimSiam 资料 深度聚类算法研究综述(很赞,从聚类方法和深度学习方法两个方面进行了总结&#xff0…...

【ARM-Linux篇】u-boot编译

一、u-boot简介 uboot是一种通用的引导加载程序,它可以用于多种嵌入式系统,支持多种操作系统,如Linux, Android,NetBSD等。uboot的主要作用是将操作系统内核从存储设备(如Flash, SD卡等)加载到内存中,并执…...

Lombok一文通

1、Lombok简介 作为java的忠实粉丝,但也不得不承认,java是一门比较啰嗦的语言,很多代码的编写远不如其他静态语言方便,更别说跟脚本语言比较了。 因此,lombok应运而生。 Lombok是一种工具库,它提供了一组…...

Seq2Seq模型:详述其发展历程、深远影响与结构深度剖析

Seq2Seq(Sequence-to-Sequence)模型是一种深度学习架构,专为处理从一个输入序列到一个输出序列的映射任务设计。这种模型最初应用于机器翻译任务,但因其灵活性和有效性,现已被广泛应用于自然语言处理(NLP&a…...

公网如何访问内网?

公网和内网已经成为我们生活中不可或缺的存在。由于内网的安全性考虑,公网无法直接访问内网资源。如何实现公网访问内网呢?本文将介绍一种名为【天联】的私有通道技术,通过安全加密,保障数据传输的安全性。 【天联】私有通道技术 …...

手机定制开发_基于天玑900的5G安卓手机定制方案

手机定制方案基于联发科天玑900强劲旗舰八核2.4GHz处理器。这款处理器采用了6nm先进制程工艺,为用户带来了痛快淋漓的性能体验。不论是进行游戏还是日常娱乐,用户都能轻松驾驭。手机搭载了最新的Android 13操作系统,提高了数据读取的准确性&a…...

免费,C++蓝桥杯等级考试真题--第2级

C蓝桥杯等级考试真题–第2级...

panic 、asset、crash 的含义和区别

在编程中,“panic” 和 “assert” 都是用于处理错误和异常情况的机制,但在不同的编程语言和框架中有一些区别。 panic: 含义:通常表示程序发生了无法恢复的错误或异常情况,需要立即终止程序的执行。 用法&#xff1…...

解决Windows 10通过SSH连接Ubuntu 20.04时的“Permission Denied”错误

在使用SSH连接远程服务器时,我们经常可能遇到各种连接错误,其中“Permission denied, please try again”是较为常见的一种。本文将分享一次实际案例的解决过程,帮助你理解如何排查并解决这类问题。 问题描述 在尝试从Windows 10系统通过SS…...

Windows 下 PostgreSQL 图形化界面安装、配置详解

相信大家对PostgreSQL都不陌生吧,自从MySQL被Oracle所控制后,PostgreSQL就成为了国内去O的首选数据库了,并且PostgreSQL目前不受任何商业公司控制,所以国内很多厂商都是基于PostgreSQL做二次开发来实现数据库自主可控的目标(国内很…...

曾巩,散文的艺术与哲思

曾巩,字子固,世称南丰先生,南丰(今江西)人,生于北宋真宗天禧三年(公元1019年),卒于北宋元丰六年(公元1083年),享年64岁。他是中国北宋…...

【SpringBoot】怎么在一个大的SpringBoot项目中创建多个小的SpringBoot项目,从而形成子父依赖

父子项目工程创建 步骤 先创建父项目 具体操作步骤请看本文章:使用maven工程创建spring boot项目 创建子项目 file- project structure module–new module 剩下步骤请看创建父工程时的操作使用maven工程创建spring boot项目 应用 确认即可 之后创建启动类…...

vue3组件通信与props

title: vue3组件通信与props date: 2024/5/31 下午9:00:57 updated: 2024/5/31 下午9:00:57 categories: 前端开发 tags: Vue3组件Props详解生命周期数据通信模板语法Composition API单向数据流 Vue 3 组件基础 在 Vue 3 中,组件是构建用户界面的基本单位&#…...

并发和异步编程:详细概述

01 Concurrency and Asynchronous Programming: a Detailed Overview 并发和异步编程:详细概述 Asynchronous programming is one of those topics many programmers find confusing. You come to the point when you think you’ve got it, only to later realize that the …...

交易员摩拳擦掌,就在今年夏天,极端气候引爆商品?

有史以来最严重的高温炙烤下,从农业到能源到航运都可能受到严重负面影响,大宗商品市场波动将大幅加剧。 2024年有望成为有史以来最炎热的一年,随着北半球步入夏季,世界各地都将遭受由全球变暖造成的极端高温困扰。极端天气不仅给民…...

数据结构学习笔记

1. 数组 (Array) 定义 数组是一种线性数据结构,用于存储固定大小的相同类型元素集合。每个元素都有一个索引,用于快速访问。 特点 优点:访问速度快,通过索引直接访问O(1)时间复杂度。缺点:大小固定,插入…...

vscode导入自定义模块报错ModuleNotFoundError解决方案

问题描述 我的项目为great_gas_or_agents,目录结构如下: log_data_extract main.py math_algorithm 现在我运行main.py,报错:from math_algorithm.utils import parse_month_match_request,ModuleNotFoundError: No …...

OpenClaw技能扩展实战:基于nanobot开发自定义自动化模块

OpenClaw技能扩展实战:基于nanobot开发自定义自动化模块 1. 为什么需要自定义技能? 去年夏天,我经常需要在出门前手动查询天气情况,这个看似简单的动作却让我感到烦躁——打开浏览器、输入网址、输入城市、查看结果。作为一个技…...

从4.69万亿Token看中国AI大模型:调用量超越美国的背后逻辑

前言最近看到一组数据:截至2026年3月15日,中国AI大模型的周调用量达到4.69万亿Token,连续第二周超越美国,全球前三全部被中国模型包揽。作为一个长期关注AI行业的技术人,这个消息让我想深入挖一挖背后的逻辑&#xff1…...

【Hi3519DV500】SD卡64G正常识别,16G和32G识别失败,报告警 mmc1: error -110 whilst initialising SD card

目录 环境 问题 定位和解决 设备树文件层次关系与覆盖原则 解决方案 方案一:修改环境变量(推荐) 方案二:修改设备树 方案三:修改硬件支持 环境 Hi3519DV500开发板 参考文档:鸿鸥派 HongOU PI V2.…...

如何快速使用LivePortrait实现AI肖像动画:终极指南

如何快速使用LivePortrait实现AI肖像动画:终极指南 【免费下载链接】LivePortrait Bring portraits to life! 项目地址: https://gitcode.com/GitHub_Trending/li/LivePortrait LivePortrait 是一款革命性的AI肖像动画工具,能够将静态照片转化为栩…...

农业图像标注效率暴跌63%?这5个Auto-Labeling技巧已获农业农村部AI应用白皮书推荐

第一章:农业图像标注效率暴跌的根源与Auto-Labeling破局逻辑农业图像标注正面临严峻效率瓶颈:单张田间作物病害图平均需人工耗时4.7分钟完成细粒度标注(含病斑轮廓、类别、严重等级三重标签),而标注错误率高达18.3%——…...

深入解析SSD的FTL:从LBA到PBA的映射机制与优化策略

1. 为什么需要FTL:SSD的"翻译官"工作原理 当你把文件保存到SSD时,操作系统只需要告诉SSD"把数据存到LBA 1234地址",完全不用关心数据实际存放在闪存芯片的哪个物理位置。这个神奇的能力全靠**FTL(闪存转换层&…...

OpCore-Simplify:如何用零代码工具在15分钟内完成黑苹果配置

OpCore-Simplify:如何用零代码工具在15分钟内完成黑苹果配置 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 对于想要在PC上安装macOS的用…...

StructBERT模型解析:从Transformer到情感分类的技术演进

StructBERT模型解析:从Transformer到情感分类的技术演进 1. 模型架构深度解析 StructBERT作为Transformer架构的重要演进,在自然语言处理领域展现出了独特的技术优势。这个模型最吸引人的地方在于,它在保持BERT强大语言理解能力的同时&…...

Realistic Vision V5.1 生态工具集成展示:与Cursor等AI编程助手联动工作流

Realistic Vision V5.1 生态工具集成展示:与Cursor等AI编程助手联动工作流 最近在尝试把各种AI工具串起来用,发现了一件挺有意思的事。以前我们做开发,写代码是一个工具,画界面图是另一个工具,做流程图还得再开一个软…...

手把手教你用Gen6D制作个人数据集:从视频采集到6D姿态估计全流程

从零构建Gen6D个人数据集:6D姿态估计实战指南 引言:为什么需要自定义6D姿态数据集? 在计算机视觉领域,6D姿态估计(6D Pose Estimation)正成为增强现实、机器人抓取和自动驾驶等应用的核心技术。与传统的2D检测不同,6…...