Python如何实现模板方法设计模式?什么是模板方法设计模式?Python 模板方法设计模式示例代码

news2024/10/6 8:32:05

什么是模板方法(Template Method)设计模式?

模板方法(Template Method)是一种行为型设计模式,它定义了一个算法的骨架,将一些步骤延迟到子类中实现。这种模式允许子类为一个算法的特定步骤提供实现,而不改变算法的结构。

在这里插入图片描述
在这里插入图片描述

模板方法模式通常包含两种类型的方法:

  1. 模板方法(Template Method): 定义了算法的骨架,提供了一个顶级的方法来定义算法的结构,这个方法通常是 final 或者不可被子类重写的。模板方法一般会调用一系列的抽象方法或者具体方法。

  2. 抽象方法(Abstract Method): 在模板方法中被声明但是没有实现,需要子类来实现具体的行为。

主要角色:

  1. 抽象类(Abstract Class): 包含模板方法和抽象方法定义算法的结构和步骤。

  2. 具体子类(Concrete Subclasses): 实现抽象类中的抽象方法,提供特定步骤的具体实现。

工作原理:

  1. 定义算法的骨架,包含一个模板方法。
  2. 模板方法定义了算法的步骤,其中某些步骤是抽象的,由子类实现。
  3. 子类提供特定步骤的实现,但整个算法的流程控制由模板方法负责。

python3 实现模板方法设计模式示例代码(一):

一个简单的示例是咖啡和茶的制备过程。制备咖啡和茶有相似的步骤(比如冲泡和加调味品),但是具体的饮料种类和调味品可能有所不同。在模板方法模式中,可以将冲泡和加调味品等步骤定义为模板方法,而具体的咖啡和茶则是子类,负责实现具体的冲泡方式和调味品。

这种模式允许在不改变算法结构的情况下,定制算法中的特定步骤。

以下是一个使用模板方法设计模式的 Python 示例,模拟了制备咖啡和茶的过程:

from abc import ABC, abstractmethod

# 抽象类定义了模板方法
class Beverage(ABC):
    def prepare(self):
        self.boil_water()
        self.brew()
        self.pour_in_cup()
        if self.customer_wants_condiments():
            self.add_condiments()

    def boil_water(self):
        print("Boiling water")

    @abstractmethod
    def brew(self):
        pass

    def pour_in_cup(self):
        print("Pouring into cup")

    @abstractmethod
    def add_condiments(self):
        pass

    # 钩子方法
    def customer_wants_condiments(self):
        return True

# 具体子类实现特定的步骤
class Coffee(Beverage):
    def brew(self):
        print("Dripping coffee through filter")

    def add_condiments(self):
        print("Adding sugar and milk")

    def customer_wants_condiments(self):
        response = input("Do you want to add sugar and milk? (y/n): ")
        return True if response.lower() == 'y' else False

class Tea(Beverage):
    def brew(self):
        print("Steeping the tea")

    def add_condiments(self):
        print("Adding lemon")

    def customer_wants_condiments(self):
        response = input("Do you want to add lemon? (y/n): ")
        return True if response.lower() == 'y' else False

# 客户端代码
if __name__ == "__main__":
    print("Making coffee...")
    coffee = Coffee()
    coffee.prepare()

    print("\nMaking tea...")
    tea = Tea()
    tea.prepare()

在这个示例中,Beverage 是抽象类,定义了制备饮料的模板方法 prepare(),以及一些抽象方法(brew()add_condiments())。CoffeeTea 类是具体的子类,分别实现了咖啡和茶的具体制作步骤。通过模板方法 prepare(),它们调用了抽象方法完成了饮料的制作。其中 customer_wants_condiments() 是一个钩子方法,允许子类控制特定步骤的实现。

python3 实现模板方法设计模式示例代码(二):

当考虑更实际的场景时,模板方法模式可以应用在日志记录中。无论是将日志记录到文件、数据库或者控制台,都有相似的流程,但每种记录方式的具体步骤略有不同。

from abc import ABC, abstractmethod

class Logger(ABC):
    def log(self):
        self.connect()
        self.format_log()
        self.write_log()
        self.disconnect()

    @abstractmethod
    def connect(self):
        pass

    @abstractmethod
    def format_log(self):
        pass

    @abstractmethod
    def write_log(self):
        pass

    @abstractmethod
    def disconnect(self):
        pass

class FileLogger(Logger):
    def connect(self):
        print("File Logger: Connecting to file...")

    def format_log(self):
        print("File Logger: Formatting log...")

    def write_log(self):
        print("File Logger: Writing log to file...")

    def disconnect(self):
        print("File Logger: Disconnecting from file...")

class DatabaseLogger(Logger):
    def connect(self):
        print("Database Logger: Connecting to database...")

    def format_log(self):
        print("Database Logger: Formatting log...")

    def write_log(self):
        print("Database Logger: Writing log to database...")

    def disconnect(self):
        print("Database Logger: Disconnecting from database...")

class ConsoleLogger(Logger):
    def connect(self):
        print("Console Logger: Connecting to console...")

    def format_log(self):
        print("Console Logger: Formatting log...")

    def write_log(self):
        print("Console Logger: Displaying log on console...")

    def disconnect(self):
        print("Console Logger: Disconnecting from console...")

if __name__ == "__main__":
    file_logger = FileLogger()
    file_logger.log()

    print("\n")

    db_logger = DatabaseLogger()
    db_logger.log()

    print("\n")

    console_logger = ConsoleLogger()
    console_logger.log()

这个示例展示了不同类型的日志记录器(文件记录、数据库记录、控制台输出)共享相同的记录流程,但具体的记录方式各不相同。Logger 类定义了模板方法 log(),而各种记录器类实现了该方法的抽象步骤。这样,无论是文件记录、数据库记录还是控制台输出,都能使用相同的模板方法进行记录。


使用模板方法设计模式时,需要注意哪些地方?

在使用模板方法设计模式时,需要注意以下几个方面:

  1. 定义模板方法: 确保模板方法中包含算法的骨架,定义了整个算法的流程和顺序。模板方法应该是 final 或者不可被子类重写,以确保算法的稳定性。

  2. 区分抽象和具体方法: 确保正确地区分抽象方法和具体方法。抽象方法应该由子类来实现,而具体方法可以在抽象类中提供默认实现。

  3. 保持一致性和稳定性: 模板方法模式旨在定义算法的骨架,并且尽可能提供稳定的算法结构。因此,在使用模板方法时,应该确保算法中的步骤是稳定和一致的。

  4. 钩子方法的使用: 如果需要在模板方法中控制特定步骤的实现,可以使用钩子方法(即具有默认实现的方法),允许子类控制或改变算法的部分步骤。

  5. 维护封装性: 确保在子类中不会直接访问或修改父类中的其他方法或属性,以保持对象的封装性。

  6. 避免滥用模板方法模式: 不要为了使用模板方法模式而人为地将一些不相关的操作强行放入模板方法中,这可能会导致类过于臃肿和难以维护。

  7. 适当的抽象级别: 考虑模板方法的抽象级别,要确保足够的抽象来适应各种子类的实现,但不要过度抽象导致子类难以实现。

总的来说,使用模板方法设计模式时,需要注意定义模板方法、合理使用抽象和具体方法、保持一致性和稳定性,以及保持良好的封装性。同时,要根据实际情况和需求适当地使用钩子方法,并避免滥用模板方法模式。


本文就到这里了,感谢您的阅读 。别忘了点赞、收藏~ Thanks♪(・ω・)ノ 🍇

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

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

相关文章

远程桌面访问MATLAB 2018B,提示License Manger Error -103,终极解决方案

通过远程桌面方位Windows Server系统下的MATLAB2018B,报错License Manger Error -103,Crack文件夹下的dll文件已经替换,同时也已经输出了lic文件,但是仍然无法打开。但是在本地桌面安装就没有问题。初步怀疑MATLAB的License使用机…

Java实现象棋算法

象棋算法包括搜索算法、评估函数和剪枝算法。以下是一个简单的实现: 搜索算法:使用极大极小值算法,即每个玩家都会做出最好的选择,考虑到对方也会做出最好的选择,所以需要搜索多层。 public int search(int depth, i…

UE5 操作WebSocket

插件:https://www.unrealengine.com/marketplace/zh-CN/product/websocket-client 参考:http://dascad.net/html/websocket/bp_index.html 1. 安装Plugings 2.测试websocket服务器 http://www.websocket-test.com/ 3.连接服务器 如果在Level BP里使用&a…

武汉站--ChatGPT/GPT4科研技术应用与AI绘图及论文高效写作

2023年随着OpenAI开发者大会的召开,最重磅更新当属GPTs,多模态API,未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义,不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车…

传输层协议 - TCP(Transmission Control Protocol)

文章目录: TCP 协议关于可靠性TCP 协议段格式序号与确认序号六个标志位16位窗口大小 确认应答(ACK)机制超时重传机制连接管理机制连接建立(三次握手)连接终止(四次挥手)TIME_WAIT 状态CLOSE_WAI…

5.2 Windows驱动开发:内核取KERNEL模块基址

模块是程序加载时被动态装载的,模块在装载后其存在于内存中同样存在一个内存基址,当我们需要操作这个模块时,通常第一步就是要得到该模块的内存基址,模块分为用户模块和内核模块,这里的用户模块指的是应用层进程运行后…

经典双指针算法试题(一)

📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、移动零1、题目讲解2、讲解算法原理3、代码实现 二、复写零1、题目讲解2、讲解算法原理3、…

Spring-IOC-@Import的用法

1、Car.java package com.atguigu.ioc; import lombok.Data; Data public class Car {private String cname; }2、 MySpringConfiguration2.java package com.atguigu.ioc; import org.springframework.context.annotation.Bean; import org.springframework.context.annotatio…

VBA技术资料MF85:将工作簿批量另存为PDF文件

我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。我的教程一共九套,分为初级、中级、高级三大部分。是对VBA的系统讲解,从简单的入门,到…

香港科技大学广州|机器人与自主系统学域博士招生宣讲会—同济大学专场!!!(暨全额奖学金政策)

在机器人和自主系统领域实现全球卓越—机器人与自主系统学域 硬核科研实验室,浓厚创新产学研氛围! 教授亲临现场,面对面答疑解惑助攻申请! 一经录取,享全额奖学金1.5万/月! 🕙时间:…

mac 和 windows 相互传输文件【共享文件夹】

文章目录 前言创建共享文件夹mac 连接共享文件夹 前言 温馨提示:mac 电脑和 windows 电脑必须处于同一局域网下 本文根据创建共享文件夹的方式实现文件互相传输,所以两台电脑必须处于同一网络 windows 创建共享文件夹,mac 电脑通过 windows…

Mrakdown Nice:格式

标题 缩进 删除线 斜体 加粗

EANet:用于医学图像分割的迭代边缘注意力网络

EANet: Iterative edge attention network for medical image segmentation EANet:用于医学图像分割的迭代边缘注意力网络背景贡献实验方法Dynamic scale-aware context module(动态规模感知上下文模块)Edge attention preservation module&a…

【日常总结】Swagger-ui 导入 showdoc (优雅升级Swagger 2 升至 3.0)

一、场景 环境: 二、存在问题 三、解决方案 四、实战 - Swagger 2 升至 3.0 (Open API 3.0) Stage 1:引入Maven依赖 Stage 2:Swagger 配置类 Stage 3:访问 Swagger 3.0 Stage 4:获取 js…

pycharm 控制台中文乱码处理

今天使用pycharm,发现控制台输出又中文乱码了,看网上很多资料说把编码改为UTF-8,设置为并未生效,特此在此记录下本地设置。 1. 修改文件编码:Setting -> Editor ->File Encodings,修改配置如下: 2. …

Windows10环境下Python解析pacp文件

Windows10环境下Python解析pacp文件 一、背景 在Python中,你可以使用scapy库来解析pcap文件。scapy是一个功能强大的网络分析工具,可以用于解析、构建和发送网络数据包。 二、环境安装 命令在终端中安装: pip install scapy由于我使用的Pycharm,所以我就直接在Python Int…

释放搜索潜力:基于Docker快速搭建ES语义检索系统(快速版),让信息尽在掌握

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

聚焦操作系统迁移痛点,麒麟信安受邀参加 openEuler Meetup苏州站分享迁移实践干货

随着数字化转型持续深入,操作系统正在向支持多样性计算、支持全场景等方向不断发展。日前,由开放原子开源基金会指导,openEuler社区、移动云联合主办的迁移主题Meetup在苏州举办,邀请来自不同领域的技术专家分享系统迁移实践案例。…

QT打包圆心识别

圆心点识别QT界面封装 最近在练习QT相关内容,找了个相关功能集成了下,主要是为了熟悉各个组件,功能主要是进行圆心识别。 主要涉及的QT功能点: 1.日志可视化 2.按钮及各类参数添加组件 3.水印添加及图片可视化 4.许可添加 5.主线…

URDF文件

URDF(Universal Robot Description Format):通用机器人描述格式,包含的内容有:连杆、关节,运动学和动力学参数、可视化模型、碰撞检测模型等。 父子关系树:连杆link1 --> 关节joint1 -->…