【设计模式】行为型-模板方法模式

方法千变万化,心灵如潮,模板如画,画出生活的韵味。

文章目录

  • 一、茶与咖啡
  • 二、模板方法模式
  • 三、模板方法模式的核心组成
  • 四、运用模板方法模式
  • 五、模板方法模式的应用场景
  • 六、小结
  • 推荐阅读

一、茶与咖啡

场景假设:我们需要完成茶和咖啡的制作。

// 咖啡类
class Coffee {// 准备配方的方法void prepareRecipe() {boilWater(); // 煮沸水brewCoffeeGrinds(); // 冲泡咖啡pourInCup(); // 倒入杯子addSugarAndMilk(); // 添加糖和牛奶}// 下面是每个步骤的具体实现void boilWater() { System.out.println("Boiling water"); }void brewCoffeeGrinds() { System.out.println("Dripping Coffee through filter"); }void pourInCup() { System.out.println("Pouring into cup"); }void addSugarAndMilk() { System.out.println("Adding Sugar and Milk"); }
}// 茶类
class Tea {// 准备配方的方法void prepareRecipe() {boilWater(); // 煮沸水steepTeaBag(); // 浸泡茶包pourInCup(); // 倒入杯子addLemon(); // 添加柠檬}// 下面是每个步骤的具体实现void boilWater() { System.out.println("Boiling water"); }void steepTeaBag() { System.out.println("Steeping the tea"); }void pourInCup() { System.out.println("Pouring into cup"); }void addLemon() { System.out.println("Adding Lemon"); }
}

咖啡和茶创建两个不同的类,并在每个类中实现整个制作过程。这将导致大量的代码重复,因为煮沸水和倒入杯子的步骤对于咖啡和茶来说都是相同的。在这个例子中,boilWaterpourInCup 在两个类中都是重复的。如果我们需要修改这些步骤的实现,我们需要在两个类中都进行修改,这就增加了维护的复杂性。此外,如果我们需要添加一个新的饮料类型,我们又需要复制大量的代码。

二、模板方法模式

模板方法模式是一种行为型设计模式,它定义了一个算法的骨架,将算法的某些步骤延迟到子类中实现。这样可以在不改变算法结构的情况下,允许子类重新定义算法中的特定步骤。

该模式提供了一个模板(即抽象类),其中包含了一系列的方法,其中某些方法是抽象的,需要由子类实现,而其他方法是具体的,并且已经实现好了。这样,当客户端调用模板方法时,将按照模板的定义来执行一系列的步骤,其中部分步骤可能在子类中有不同的实现。

三、模板方法模式的核心组成

模板方法模式的核心组件主要包括以下几个部分:

  1. 抽象类(Abstract Class):这个类定义了一系列的方法,包括具体的方法(实现了特定功能)和抽象的方法(没有具体实现,需要子类来提供实现)。此外,抽象类还定义了一个模板方法,这个方法按照特定的顺序调用上述的一系列方法。
  2. 具体类(Concrete Class):这个类继承自抽象类,并提供抽象方法的具体实现。当模板方法被调用时,这些具体的实现将被执行。
  3. 模板方法(Template Method):在抽象类中定义,这个方法包含了一个算法的骨架。它按照特定的顺序调用一系列的方法。其中一些方法是具体的,由抽象类提供实现;另一些方法是抽象的,由具体类提供实现。
  4. 钩子方法(Hook Method):这是一种特殊的方法,它在抽象类中通常没有做任何事或者只提供默认的实现,但是它提供了一个扩展点,允许子类在必要时覆盖它。

在这里插入图片描述

在这个类图中:

  1. AbstractClass 是一个抽象类,它定义了 templateMethod()(模板方法)和两个抽象方法 primitiveOperation1() 和 primitiveOperation2()。模板方法定义了一个算法的骨架,按照特定的顺序调用一系列的方法。其中一些方法是具体的,由抽象类提供实现;另一些方法是抽象的,由具体类提供实现。
  2. ConcreteClass 是一个具体类,它继承自 AbstractClass 并提供抽象方法的具体实现。当模板方法被调用时,这些具体的实现将被执行。

四、运用模板方法模式

场景假设:我们需要制作茶、咖啡等多种饮料。

  1. 定义抽象类:首先,我们需要定义一个抽象类,这个类包含了制作饮料的通用步骤。

    // 抽象类:含有咖啡因的饮料
    abstract class CaffeineBeverage {// 这是我们的模板方法。它定义了算法的步骤。final void prepareRecipe() {boilWater(); // 第一步:煮沸水brew(); // 第二步:冲泡。但是我们并不知道是冲泡咖啡还是茶,所以这是一个抽象方法。pourInCup(); // 第三步:倒入杯子addCondiments(); // 第四步:添加调料。但是我们并不知道是添加什么调料,所以这是一个抽象方法。}// 这两个方法是抽象的,也就是说,我们需要子类来提供具体的实现。abstract void brew();abstract void addCondiments();// 这两个方法是具体的,也就是说,它们在所有子类中都是一样的,所以我们可以将它们的实现放在这个抽象类中。void boilWater() { System.out.println("Boiling water"); }void pourInCup() { System.out.println("Pouring into cup"); }
    }
    

    在这个抽象类 CaffeineBeverage 中,我们定义了一个模板方法 prepareRecipe(),它按照特定的顺序调用一系列的步骤。其中 brew() 和 addCondiments() 是抽象的,我们需要子类来提供具体的实现。

  2. 定义具体类:然后,我们为每种饮料定义一个具体的类,这个类继承自抽象类,并提供抽象方法的具体实现。

    // 具体类:咖啡
    class Coffee extends CaffeineBeverage {// 对于咖啡来说,冲泡就是用热水过滤咖啡void brew() {System.out.println("Dripping Coffee through filter");}// 对于咖啡来说,添加的调料是糖和牛奶void addCondiments() {System.out.println("Adding Sugar and Milk");}
    }// 具体类:茶
    class Tea extends CaffeineBeverage {// 对于茶来说,冲泡就是用热水浸泡茶叶void brew() {System.out.println("Steeping the tea");}// 对于茶来说,添加的调料是柠檬void addCondiments() {System.out.println("Adding Lemon");}
    }
    

    在这两个具体类 Coffee 和 Tea 中,我们提供了 brew() 和 addCondiments() 方法的具体实现。当模板方法 prepareRecipe() 被调用时,这些具体的实现将被执行。

五、模板方法模式的应用场景

模板方法模式通常在以下情况下使用:

  1. 算法框架固定,但具体实现可变:当一个算法的框架已经确定,但其中的一些步骤的具体实现可能会随着应用场景的变化而变化时,可以使用模板方法模式。这样,可以将算法的框架定义在抽象模板中,而将可变的部分留给子类来实现。
  2. 避免代码重复:当多个类中存在相似的算法流程,但具体步骤略有不同,为避免代码重复,可以将这些公共部分提取到抽象模板中,从而避免代码重复,提高代码的复用性。
  3. 提供算法定制化的扩展点:模板方法模式提供了一种在不改变算法结构的情况下,允许子类重新定义算法中特定步骤的方法。这样,可以为客户端提供一种定制化的扩展点,允许客户端根据需要定制算法的具体实现。
  4. 框架设计:模板方法模式在框架设计中也经常被使用,例如在 Web 框架中,可以定义一个抽象的控制器类作为模板,其中包含了请求处理的流程,而具体的控制器类则根据具体业务需求来实现这些步骤。

六、小结

模板方法模式能够帮助我们定义算法的骨架,并允许子类定制算法的具体实现,从而提高了代码的复用性和灵活性,是一种非常有用的设计模式。在实际开发中,我们可以根据具体情况来灵活运用模板方法模式,提高代码的可维护性和扩展性。

推荐阅读

  1. Spring 三级缓存
  2. 深入了解 MyBatis 插件:定制化你的持久层框架
  3. Zookeeper 注册中心:单机部署
  4. 【JavaScript】探索 JavaScript 中的解构赋值
  5. 深入理解 JavaScript 中的 Promise、async 和 await

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

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

相关文章

基于Unet++在kaggle—2018dsb数据集上实现图像分割

目录 1. 作者介绍2. 理论知识介绍2.1 Unet模型介绍 3. 实验过程3.1 数据集介绍3.2 代码实现3.3 结果 4. 参考链接 1. 作者介绍 郭冠群,男,西安工程大学电子信息学院,2023级研究生 研究方向:机器视觉与人工智能 电子邮件&#xff…

Go变量作用域精讲及代码实战

1. 变量的作用域概述 在编程中,变量的作用域(Scope)定义了变量在程序中的可见性和生命周期。理解变量的作用域对于编写健壮且可维护的代码至关重要。Go语言(简称Go)提供了几种不同的作用域类型,使得开发者可…

C++:十大排序

目录 时间复杂度分析 选择排序 引言 算法思想 动图展示 代码实现 (升序) 优化 代码实现 分析 冒泡排序 引言 算法思想 动图展示 代码实现 插入排序 引言 算法思想 动图展示 代码实现 计数排序 引言 算法思想 动图展示 代码实现 桶排序 引言 算法思…

利安科技上市首日股价大涨:2023营收净利润下滑,募资金额大幅缩水

《港湾商业观察》施子夫 6月7日,宁波利安科技股份有限公司(以下简称,利安科技)正式在深交所创业板挂牌上市,股票简称为利安科技,股票代码300784。 上市当天,利安科技股价大涨348.76%。 2022年…

46.Python-web框架-Django - 多语言配置

目录 1.Django 多语言基础知识 1.1什么是Django国际化和本地化? 1.2Django LANGUAGE_CODE 1.3关于languages 1.4RequestContext对象针对翻译的变量 2.windows系统下的依赖 3.django多语言配置 3.1settings.py配置 引用gettext_lazy 配置多语言中间件&#x…

set与map的详细封装步骤

目录 一.set与map在STL中的源码 二.修改红黑树 1.插入与查找时的比较方式 2.插入时的返回值 3.补充成员函数 三.封装set与map 1.迭代器的实现 2.函数接口 3.map中的operator[] 四.完整代码 set.h map.h RBTree.h 一.set与map在STL中的源码 想要简单实现set与map 需…

短视频矩阵工具有哪些?如何辨别是否正规?

随着短视频平台的持续火爆,搭建短视频矩阵成为各大品牌商家提高营销效果和完成流量变现的主要方式之一,类似于短视频矩阵工具有哪些等问题也在多个社群有着不小的讨论度。 而就短视频矩阵工具的市场现状而言,其整体呈现出数量不断增长&#x…

使用神卓互联来访问单位内部web【内网穿透神器】

在现代工作环境中,有时我们需要从外部访问单位内部的 web 资源,而神卓互联这款内网穿透神器就能完美地满足这一需求。 使用神卓互联来访问单位内部 web 其实并不复杂,以下是大致的使用步骤和配置方法。 首先,我们需要在单位内部的…

Three.js做了一个网页版的我的世界

前言 笔者在前一阵子接触到 Three.js 后, 发现了它能为前端 3D 可视化 / 动画 / 游戏方向带来的无限可能, 正好最近在与朋友重温我的世界, 便有了用 Three.js 来仿制 MineCraft 的想法, 正好也可以通过一个有趣的项目来学习一下前端 3D 领域 介绍 游戏介绍 相信大家对我的世…

vue3+ Element-Plus 点击勾选框往input中动态添加多个tag

实现效果&#xff1a; template&#xff1a; <!--产品白名单--><div class"con-item" v-if"current 0"><el-form-item label"平台名称"><div class"contaion" click"onclick"><!-- 生成的标签 …

Unity HoloLens2 MRTK 空间锚点 基础教程

Unity HoloLens2 MRTK 空间锚点 基础教程 Unity HoloLens2 空间锚点MRTK 空间锚点 准备Unity 工程创建设置切换 UWP 平台UWP 平台设置 下载并安装混合现实功能工具导入混合现实工具包和 OpenXR 包 Unity 编辑器 UWP 设置Unity 2019.4.40 设置Unity 2022.3.0 设置Unity 2022.3.0…

KCC@深圳-升压手电制作活动

这次我们将制作一款工业风升压手电。电路简单&#xff0c;适合入门型选手。也会进行原理讲解&#xff0c;方便大家升级改造。 活动概览 活动主题升压手电制作活动时间6月16日&#xff08;周日&#xff09;13:30活动地点月亮湾山庄A13人数限制15合作伙伴706深圳&#xff08;706青…

C语言----字符函数和字符串函数

在编程的过程中&#xff0c;我们要经常处理字符和字符串&#xff0c;为了方便操作字符和字符串&#xff0c;c语言标准库中提供的一系列库函数&#xff0c;接下来我们就开始学习与认识他们 1.字符分类函数 c语言中有一系列的函数是专门做字符分类的&#xff0c;也就是一个字符…

「漏洞复现」I Doc View 在线文档预览 qJvqhFt.json 任意文件读取漏洞(XVE-2024-2115)

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

解决electron设置透明背景后,引入element-plus样式问题

首先给当前窗口设置自定义窗口以及背景色。 const mainWindow new BrowserWindow({width: 900,height: 670,show: false,autoHideMenuBar: true,...(process.platform linux ? { icon } : {}),webPreferences: {preload: join(__dirname, ../preload/index.js),sandbox: fal…

【 EI会议 | 西南大学主办 | 往届均已实现检索】第三届神经形态计算国际会议(ICNC 2024)

第三届神经形态计算国际会议&#xff08;ICNC 2024) 2024 3rd International Conference on Neuromorphic Computing (ICNC 2024) 一、重要信息 大会官网&#xff1a;www.ic-nc.org&#xff08;点击投稿/参会/了解会议详情&#xff09; 会议时间&#xff1a;2024年12月13-15…

Elasticsearch:智能 RAG,获取周围分块

作者&#xff1a;来自 Elastic Sunile Manjee 在检索增强生成 (RAG) 领域&#xff0c;一个持续存在的挑战是找到输入大型语言模型 (LLM) 的最佳数据量。数据太少会导致响应不足或不准确&#xff0c;而数据太多会导致答案模糊。这种微妙的平衡启发我开发了一个专注于智能分块和利…

社区论坛圈子软件APP ,提供互动交流、知识共享和专业交流的社交平台。

社区论坛圈子软件APP的开发能够为用户提供一个互动交流的社交平台&#xff0c;促进用户之间的知识分享、交流和互助。本文将突出社区论坛圈子软件APP的前景、作用和特点&#xff0c;以帮助您了解该系统的潜力和优势。 一、前景&#xff1a; 知识共享&#xff1a;社区论坛圈子软…

力扣每日一题-419

题目 给你一个大小为 m x n 的矩阵 board 表示甲板&#xff0c;其中&#xff0c;每个单元格可以是一艘战舰 X 或者是一个空位 . &#xff0c;返回在甲板 board 上放置的 战舰 的数量。 战舰 只能水平或者垂直放置在 board 上。换句话说&#xff0c;战舰只能按 1 x k&#xff…

一带一路情 相逢《中国缘》-诗琳探访湘西墨戎苗寨交流有感

一带一路情 相逢《中国缘》 诗琳探访湘西墨戎苗寨交流有感 5月21日至25日&#xff0c;《中国缘》栏目组组织的走进湘西苗疆边陲的文化交流活动&#xff0c;在群山环抱、绿树成荫、人文厚重的湘西古丈墨戎苗寨美丽绽放。这场以民间角度推演的中国和中亚人民的文化交流活动&am…