趣谈设计模式之模板方法模式-老板,你的数字咖啡制作好了,请享用!

模板方法模式

定义了一套算法的骨架,讲某些具体的步骤延迟到子类中实现。 主要用于不改变算法结构的情况下重新定义算法的某些步骤,以适应新的需求。

模板方法的角色
  • 抽象类: 作为算法的骨架,该抽象类中包含了算法的核心部分和一些抽象方法,也可能包含一些具体方法,其中抽象方法表示算法中需要子类实现的具体步骤
  • 具体子类:继承抽象类,实现抽象方法以完成算法的具体步骤。 子类也可以实现一些 钩子方法 以影响算法的执行。
模板方法的优缺点

优点:

  • 提高代码的复用性
  • 提高代码的可扩展性
  • 符合开闭原则

缺点:

  • 抽象类和具体子类之间耦合度较高(组合优于继承),抽象类发生变化时,可能会影响到所有子类,比如父类增加新的抽象方法,那么所有的子类需要都实现一遍。
应用场景
  • 自上而下的父类视角:在抽象类中实现一个算法的公共部分,将可变的部分 留给具体子类实现
  • 自下而上的子类视角:将子类中的公共部分提取出来,集中到父类中,避免代码重复

示例场景: 文档处理器
假设我们有一个文档处理器,它需要执行以下步骤:

打开文档
解析文档内容
处理文档内容
保存处理后的文档

from abc import ABC, abstractmethod# 抽象类:文档处理器
class DocumentProcessor(ABC):def process_document(self):"""模板方法,定义处理文档的步骤"""self.open_document()content = self.parse_document()processed_content = self.handle_content(content)self.save_document(processed_content)@abstractmethoddef open_document(self):"""抽象方法:打开文档"""pass@abstractmethoddef parse_document(self):"""抽象方法:解析文档内容"""passdef handle_content(self, content):"""默认实现:处理文档内容"""# 默认处理逻辑,子类可以重写return content.upper()@abstractmethoddef save_document(self, processed_content):"""抽象方法:保存处理后的文档"""pass# 具体类:PDF文档处理器
class PDFProcessor(DocumentProcessor):def open_document(self):print("打开PDF文档")def parse_document(self):print("解析PDF内容")return "PDF内容"def save_document(self, processed_content):print(f"保存处理后的PDF内容:{processed_content}")# 具体类:Word文档处理器
class WordProcessor(DocumentProcessor):def open_document(self):print("打开Word文档")def parse_document(self):print("解析Word内容")return "Word内容"def save_document(self, processed_content):print(f"保存处理后的Word内容:{processed_content}")def handle_content(self, content):# 重写处理内容的方法return content.lower()# 测试代码
def main():# 创建PDF处理器实例pdf_processor = PDFProcessor()pdf_processor.process_document()print("\n")# 创建Word处理器实例word_processor = WordProcessor()word_processor.process_document()if __name__ == "__main__":main()
虚构故事

接-上一节讲的状态模式之比特咖啡故事。比特咖啡的故事-传送门, 老板姬比特要给比特咖啡研发两款数字咖啡产品并通过这两款引流想打造成爆款(美式和卡布奇诺), 程序员-幸瑞接过了这个活,他使用-模板方法模式设计了数字咖啡的制作流程。
且看他的代码是如何实现的。

from abc import ABC, abstractmethodclass CoffeeMaker(ABC):def make_coffee(self):"""模板方法,定义制作咖啡的整体流程"""self.grind_coffee()self.brew_coffee()self.add_ingredients()self.finish_coffee()@abstractmethoddef grind_coffee(self):"""抽象方法:研磨咖啡豆"""pass@abstractmethoddef brew_coffee(self):"""抽象方法:冲泡咖啡"""passdef add_ingredients(self):"""默认方法:添加配料"""# 默认不添加任何配料,子类可以重写pass@abstractmethoddef finish_coffee(self):"""抽象方法:完成咖啡制作"""pass

代码写到这,骨架算是搭建起来了,幸瑞准备去外面抽根烟休息一会,刚要锁屏起身时,老板-姬比特走了过来看到屏幕一堆pass,一万个问号, 老幸,你搞这么多pass干什么, pass在python中是占位符表示什么也不做,我还是懂一点的,你小子是不是急着开溜摸鱼啊。
幸瑞连忙给老板解释说,我这是把数字咖啡的制作流程先抽象了出来,具体的实现方式还没写呢,办公室这会有点闷,我先出去透透气,顺便梳理下思路。 随后,幸瑞按下了win+L潇洒的离去。 只剩下老板愣在原地表情瞬间凝固。

20min later…
幸瑞缓缓的走进办公室开始干活,见他飞快的敲击着新买的Filco机械键盘,声音响彻狭小的办公室。 不一会儿又安静了下来。 原来功能已经实现了,接下来我们看看他是如何实现的。
首先,他创建两个具体的子类 AmericanoMaker 和 CappuccinoMaker,分别对应美式咖啡和卡布奇诺的制作步骤。

class AmericanoMaker(CoffeeMaker):def grind_coffee(self):print("研磨中度烘焙的咖啡豆")def brew_coffee(self):print("用热水冲泡咖啡,制作美式咖啡")def add_ingredients(self):print("加入适量的热水")def finish_coffee(self):print("美式咖啡制作完成,可以享用了!")class CappuccinoMaker(CoffeeMaker):def grind_coffee(self):print("研磨深度烘焙的咖啡豆")def brew_coffee(self):print("用蒸汽牛奶冲泡咖啡,制作卡布奇诺")def add_ingredients(self):print("打发牛奶并加入奶泡")def finish_coffee(self):print("卡布奇诺制作完成,可以享用了!")# 接着,为了验证设计是否正确,编写了测试代码,分别创建美式咖啡和卡布奇诺的制作实例,并调用 make_coffee 方法
def main():# 创建美式咖啡制作实例americano_maker = AmericanoMaker()print("制作美式咖啡:")americano_maker.make_coffee()print("\n")# 创建卡布奇诺制作实例cappuccino_maker = CappuccinoMaker()print("制作卡布奇诺:")cappuccino_maker.make_coffee()if __name__ == "__main__":main()# 运行结果如下
制作美式咖啡:
研磨中度烘焙的咖啡豆
用热水冲泡咖啡,制作美式咖啡
加入适量的热水
美式咖啡制作完成,可以享用了!制作卡布奇诺:
研磨深度烘焙的咖啡豆
用蒸汽牛奶冲泡咖啡,制作卡布奇诺
打发牛奶并加入奶泡
卡布奇诺制作完成,可以享用了!

老板,你的数字咖啡制作好了,请享用! 幸瑞大声的说道,办公室的N多双眼睛瞬间将焦点转移到了幸瑞的工位上…

欲知后事如何,点赞关注不迷路,比特咖啡的故事还会继续讲下去.

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

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

相关文章

技术栈:基于Java语言的搭子_搭子社交_圈子_圈子社交_搭子小程序_搭子APP平台

一、市场背景1、社会发展与生活方式转变城市化进程加快:随着城市化不断推进,大量人口涌入城市,人们生活的物理空间距离拉近了,但人际关系却在一定程度上变得疏离。传统的基于血缘、地缘建立起的紧密社交关系难以满足城市生活中的多…

字典在VBA与VB.NET的区别,举例说明

简述:在VBA中,字典通常使用Scripting.Dictionary对象,通过CreateObject("Scripting.Dictionary")创建。它需要引用Microsoft Scripting Runtime库(scrrun.dll)。VBA字典的方法包括Exists、Add、Remove等&…

2024年网络安全案例

以下是2024年造成严重损失的网络安全典型案例,涵盖市政系统、金融交易、区块链平台、国家级攻击及全球性IT故障五大领域,按损失规模和技术危害性综合排序:---一、市政基础设施攻击 1. 加拿大汉密尔顿市勒索软件事件 - 损失:183…

PINN+贝叶斯:深度学习中的魔改新思路

2025深度学习发论文&模型涨点之——PINN贝叶斯PINN通过将物理定律(如偏微分方程PDEs)嵌入神经网络的损失函数中,使得模型能够利用已知的物理规律来指导学习过程,从而在数据有限或噪声较多的情况下实现更高的准确性。然而&…

零基础-动手学深度学习-8.3. 语言模型和数据集

很至关重要的一章: 8.3.1. 学习语言模型 8.3.2. 马尔可夫模型与n元语法 n元语法看的序列长度是固定的, 存储的序列长是有限且可控的,使用统计方法的时候通常使用这个模型!!!统计方法!!&#x…

C++ 模板初阶

什么是模板? 模板(Template)是 C 中实现泛型编程的核心工具。它允许我们编写与具体数据类型无关的代码,从而实现代码复用和类型安全。为什么需要模板? 举个生活中的例子:如果你要造一个能装水的杯子&#x…

DockerFile文件执行docker bulid自动构建镜像

文章目录一、Dockerfile介绍二、Dockerfile镜像制作和流程使用三、Dockerfile文件的制作镜像的分层结构四、Dockerfile文件格式五、Dockerfile相关指令5.1 FROML:指定基础镜像5.2 LABEL:指定镜像元数据5.3 RUN:执行shell指令5.4 ENV&#xff…

osloader!DoGlobalInitialization函数分析之HW_CURSOR--NTLDR源代码分析之设置光标

第一部分: VOID DoGlobalInitialization(IN PBOOT_CONTEXT BootContextRecord){//// Turn the cursor off//HW_CURSOR(0,127);D:\srv03rtm\base\boot/inc/bldrx86.h:258:#define HW_CURSOR (*ExternalServicesTable->HardwareCursor)第二部分&#xff…

Elasticsearch 索引及节点级别增删改查技术

以下是针对 Elasticsearch 索引及节点级别增删改查技术做的简短总结&#xff1a; 一、索引操作创建索引 功能&#xff1a;指定分片、副本数及映射规则[2][4]。示例&#xff1a;PUT /<index_name>​&#xff0c;可定义 settings&#xff08;如分片数&#xff09;和 mappin…

烽火HG680-KD_海思MV320处理器-安卓9-原厂系统升级包-针对解决烧录不进系统的问题

烽火HG680-KD_海思MV320处理器-安卓9-原厂系统升级包&#xff08;注意是&#xff08;原机系统&#xff09;&#xff09;-主要是针对解决TTL烧录后仍然不进系统使用。HG680-KD&#xff0f;HG680-KE&#xff0f;HG680-KF&#xff0f;HG680-KX 均通用。 说明&#xff1a; 前一个…

VS2019安装HoloLens 没有设备选项

第一步先检查VS有没有安装C组件第二步把VS工程最后一个设置为启动项

【云计算】云主机的亲和性策略(二):集群节点组

《云主机的亲和性策略》系列&#xff0c;共包含以下文章&#xff1a; 1️⃣ 云主机的亲和性策略&#xff08;一&#xff09;&#xff1a;快乐旅行团2️⃣ 云主机的亲和性策略&#xff08;二&#xff09;&#xff1a;集群节点组3️⃣ 云主机的亲和性策略&#xff08;三&#xf…

【人工智能】AI代理在零售业的崛起:从草莓订购到全流程购物体验

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在零售业快速演变的格局中,AI代理正作为变革力量崛起,连接消费者需求与无缝履行。本文深入探讨AI代理在零售中的兴起,从通过对话界面订购…

【读论文】从Qwen3技术报告到Qwen3-30B-A3B 模型的深度解读

引言:当大模型追求又小又好用 最近都是各种新大模型满天飞,其中Qwen3-30B-A3B-Instruct-2507很是亮眼,这种参数尺寸是相对友好的,效果好而且模型不大。从这里就引发一下疑问,如何在保证强大能力的同时,兼顾模型的效率和可访问性?毫无疑问,混合专家 (Mixture-of-Expert…

【番外篇15】中心极限定理:从数学原理到生活案例

一、什么是中心极限定理&#xff1f;中心极限定理(Central Limit Theorem, CLT)是概率论与统计学中最重要的定理之一&#xff0c;它揭示了为什么正态分布在自然界和统计学中如此普遍。​定理表述​&#xff1a;设X₁, X₂, ..., Xₙ 是一组独立同分布的随机变量序列&#xff0c…

本地构建Docker镜像并推送到GitHub Container Registry

一、本地构建并推送镜像1. 登录GitHub Container Registry首先&#xff0c;需要登录到GitHub Container Registry (GHCR)&#xff1a;# 使用个人访问令牌(PAT)登录 docker login ghcr.io -u 你的GitHub用户名 -p 你的个人访问令牌注意&#xff1a;你需要在GitHub上创建一个具有…

DP-v2.1-mem-clean学习(3.6.8-3.6.8.1)

3.6.8 lttpr非透明模式下的链路训练 3.6.8.1 支持8b/10b链路层训练规范 ‌默认透明模式‌ 若上游设备未启用LTTPR非透明模式(Non-transparent),需在链路训练前将DPCD F0003h寄存器写入默认值55h38 ‌非法中继器计数值处理‌ 当DPCD F0002h(PHY_REPEATER_CNT)返回值非有…

kali安装maven

kali安装maven 下载maven的安装包 wget https://dlcdn.apache.org/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.tar.gz 注意可能返回404&#xff0c;这是因为官网已经更新了版本&#xff0c;这种情况可以自己访问https://dlcdn.apache.org/maven/maven-3查看一下最…

GEO优化:品牌营销新战场的光明与荆棘

在AI重塑信息获取方式的今天&#xff0c;一种名为GEO&#xff08;生成式引擎优化&#xff09;​的策略正悄然成为企业营销版图的新坐标。它不追求传统搜索引擎中的链接排名&#xff0c;而是争夺生成式AI&#xff08;如ChatGPT、DeepSeek等&#xff09;答案中的“话语权”——让…

牛客 - 旋转数组的最小数字

描述 有一个长度为 n 的非降序数组&#xff0c;比如[1,2,3,4,5]&#xff0c;将它进行旋转&#xff0c;即把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;变成一个旋转数组&#xff0c;比如变成了[3,4,5,1,2]&#xff0c;或者[4,5,1,2,3]这样的。请问&#xff0c;给定这…