灵活多变的对象创建——工厂方法模式(Python实现)

1. 引言

大家好,又见面了!在上一篇文章中,我们聊了聊简单工厂模式,今天,我们要进一步探讨一种更加灵活的工厂设计模式——工厂方法模式。如果说简单工厂模式是“万能钥匙”,那工厂方法模式就是“变形金刚”。它通过定义一个创建对象的接口,让子类决定实例化哪一个类,从而应对各种变化。今天,我们就来揭开工厂方法模式的神秘面纱,让你的Python代码更加灵活多变。准备好了吗?Let’s go!

2. 什么是工厂方法模式

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式使一个类的实例化延迟到其子类,简而言之,就是父类提供一个接口,子类来决定实例化哪个具体的类。

3. 工厂方法模式的实现(Python)

示例一:形状工厂

假如你是个艺术家,需要画各种形状,圆形、方形啥的,你可以用工厂方法模式让子类决定创建哪些形状对象:

代码实现
from abc import ABC, abstractmethod

# 定义Shape接口
class Shape(ABC):
    @abstractmethod
    def draw(self):
        pass

# 实现Circle类
class Circle(Shape):
    def draw(self):
        print("Drawing a Circle")

# 实现Square类
class Square(Shape):
    def draw(self):
        print("Drawing a Square")

# 定义ShapeFactory接口
class ShapeFactory(ABC):
    @abstractmethod
    def create_shape(self):
        pass

# 实现CircleFactory类
class CircleFactory(ShapeFactory):
    def create_shape(self):
        return Circle()

# 实现SquareFactory类
class SquareFactory(ShapeFactory):
    def create_shape(self):
        return Square()

# 使用示例
if __name__ == "__main__":
    circle_factory = CircleFactory()
    shape1 = circle_factory.create_shape()
    shape1.draw()  # 输出: Drawing a Circle

    square_factory = SquareFactory()
    shape2 = square_factory.create_shape()
    shape2.draw()  # 输出: Drawing a Square
详细代码解析
  • Shape是一个抽象基类,定义了draw抽象方法;
  • CircleSquare类实现了Shape接口,具体画啥样子它们说了算;
  • ShapeFactory是一个抽象基类,定义了create_shape抽象方法;
  • CircleFactorySquareFactory类实现了ShapeFactory接口,分别负责创建CircleSquare对象;
  • 我们只需通过调用具体的工厂类(如CircleFactorySquareFactory)来创建形状对象,然后调用相应的draw方法。
示例二:日志记录器工厂

现在你是个开发者,搞个日志系统,你想要不同级别的日志记录器来帮你分门别类记录信息,工厂方法模式也能派上用场:

码实现
from abc import ABC, abstractmethod

# 定义Logger接口
class Logger(ABC):
    @abstractmethod
    def log(self, message):
        pass

# 实现InfoLogger类
class InfoLogger(Logger):
    def log(self, message):
        print(f"INFO: {message}")

# 实现ErrorLogger类
class ErrorLogger(Logger):
    def log(self, message):
        print(f"ERROR: {message}")

# 定义LoggerFactory接口
class LoggerFactory(ABC):
    @abstractmethod
    def create_logger(self):
        pass

# 实现InfoLoggerFactory类
class InfoLoggerFactory(LoggerFactory):
    def create_logger(self):
        return InfoLogger()

# 实现ErrorLoggerFactory类
class ErrorLoggerFactory(LoggerFactory):
    def create_logger(self):
        return ErrorLogger()

# 使用示例
if __name__ == "__main__":
    info_logger_factory = InfoLoggerFactory()
    info_logger = info_logger_factory.create_logger()
    info_logger.log("This is an informational message.")  # 输出: INFO: This is an informational message.

    error_logger_factory = ErrorLoggerFactory()
    error_logger = error_logger_factory.create_logger()
    error_logger.log("This is an error message.")  # 输出: ERROR: This is an error message.
详细代码解析
  • Logger是一个抽象基类,定义了log抽象方法;
  • InfoLoggerErrorLogger类实现了Logger接口,分别负责记录不同级别的日志;
  • LoggerFactory是一个抽象基类,定义了create_logger抽象方法;
  • InfoLoggerFactoryErrorLoggerFactory类实现了LoggerFactory接口,分别负责创建InfoLoggerErrorLogger对象;
  • 你只需通过调用具体的工厂类(如InfoLoggerFactoryErrorLoggerFactory)来创建日志记录器对象,然后调用相应的log方法。
示例三:数据库连接工厂

假如你现在是个DBA,需要管理多个数据库连接,工厂方法模式同样能帮你搞定这个问题:

代码实现
from abc import ABC, abstractmethod

# 定义DatabaseConnection接口
class DatabaseConnection(ABC):
    @abstractmethod
    def connect(self):
        pass

# 实现MySQLConnection类
class MySQLConnection(DatabaseConnection):
    def connect(self):
        print("Connecting to MySQL database...")

# 实现PostgreSQLConnection类
class PostgreSQLConnection(DatabaseConnection):
    def connect(self):
        print("Connecting to PostgreSQL database...")

# 定义DatabaseConnectionFactory接口
class DatabaseConnectionFactory(ABC):
    @abstractmethod
    def create_connection(self):
        pass

# 实现MySQLConnectionFactory类
class MySQLConnectionFactory(DatabaseConnectionFactory):
    def create_connection(self):
        return MySQLConnection()

# 实现PostgreSQLConnectionFactory类
class PostgreSQLConnectionFactory(DatabaseConnectionFactory):
    def create_connection(self):
        return PostgreSQLConnection()

# 使用示例
if __name__ == "__main__":
    mysql_factory = MySQLConnectionFactory()
    mysql_connection = mysql_factory.create_connection()
    mysql_connection.connect()  # 输出: Connecting to MySQL database...

    postgresql_factory = PostgreSQLConnectionFactory()
    postgresql_connection = postgresql_factory.create_connection()
    postgresql_connection.connect()  # 输出: Connecting to PostgreSQL database...
详细代码解析
  • DatabaseConnection是一个抽象基类,定义了connect抽象方法;
  • MySQLConnectionPostgreSQLConnection类实现了DatabaseConnection接口,分别负责不同数据库的连接;
  • DatabaseConnectionFactory是一个抽象基类,定义了create_connection抽象方法;
  • MySQLConnectionFactoryPostgreSQLConnectionFactory类实现了DatabaseConnectionFactory接口,分别负责创建MySQLConnectionPostgreSQLConnection对象;
  • 你只需通过调用具体的工厂类(如MySQLConnectionFactoryPostgreSQLConnectionFactory)来创建数据库连接对象,然后调用相应的connect方法。

4. 工厂方法模式的优缺点

优点
  • 解耦:将对象的创建过程与使用过程分离,降低了代码的耦合度;
  • 灵活性:通过子类来决定具体实例化哪个类,增加了代码的灵活性;
  • 扩展性:增加新的产品类时,只需添加相应的工厂类即可,不需要修改现有代码。
缺点
  • 类的数量增加:每增加一个产品类,都需要增加一个相应的工厂类,导致类的数量增多;
  • 代码复杂度提高:增加了系统的复杂性,理解起来可能会有些困难。

5. 图示

类图
../_images/FactoryMethod.jpg
示意图

img

6. 总结

工厂方法模式是一个非常有用的设计模式,通过定义一个创建对象的接口,让子类来决定实例化哪一个类,增加了代码的灵活性和可扩展性。虽然它会增加类的数量和代码的复杂度,但在大多数情况下,工厂方法模式依然是一个非常实用的解决方案。希望今天的分享能让大家对工厂方法模式有更深入的理解,如果你在项目中也用到了工厂方法模式,欢迎留言分享你的经验和见解!
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Sorted Set 类型命令(命令语法、操作演示、命令返回值、时间复杂度、注意事项)

Sorted Set 类型 文章目录 Sorted Set 类型zadd 命令zrange 命令zcard 命令zcount 命令zrevrange 命令zrangebyscore 命令zpopmax 命令bzpopmax 命令zpopmin 命令bzpopmin 命令zrank 命令zscore 命令zrem 命令zremrangebyrank 命令zremrangebyscore 命令zincrby 命令zinterstor…

干货:高水平论文写作思路与方法

前言:Hello大家好,我是小哥谈。高水平论文的写作需要扎实的研究基础和严谨的思维方式。同时,良好的写作技巧和时间管理也是成功的关键。本篇文章转载自行业领域专家所写的一篇文章,希望大家阅读后可以能够有所收获。🌈 目录 🚀1.依托事实/证据,通过合理的逻辑,…

【MindSpore学习打卡】应用实践-热门LLM及其他AI应用-使用MindSpore实现K近邻算法对红酒数据集进行聚类分析

在机器学习领域,K近邻算法(K-Nearest Neighbor, KNN)是最基础且常用的算法之一。无论是分类任务还是回归任务,KNN都能通过简单直观的方式实现高效的预测。在这篇博客中,我们将基于MindSpore框架,使用KNN算法…

for nested data item, row-key is required.报错解决

今天差点被一个不起眼的bug搞到吐,就是在给表格设置row-key的时候,一直设置不成功,一直报错缺少row-key,一共就那两行代码 实在是找不到还存在什么问题... 先看下报错截图... 看下代码 我在展开行里面用到了一个表格 并且存放表格…

【算法】代码随想录之数组(更新中)

文章目录 前言 一、二分查找法(LeetCode--704) 二、移除元素(LeetCode--27) 前言 跟随代码随想录,学习数组相关的算法题目,记录学习过程中的tips。 一、二分查找法(LeetCode--704&#xff0…

WEB安全基础:网络安全常用术语

一、攻击类别 漏洞:硬件、软件、协议,代码层次的缺陷。 后⻔:方便后续进行系统留下的隐蔽后⻔程序。 病毒:一种可以自我复制并传播,感染计算机和网络系统的恶意软件(Malware),它能损害数据、系统功能或拦…

实战 | YOLOv8使用TensorRT加速推理教程(步骤 + 代码)

导 读 本文主要介绍如何使用TensorRT加速YOLOv8模型推理的详细步骤与演示。 YOLOv8推理加速的方法有哪些? YOLOv8模型推理加速可以通过多种技术和方法实现,下面是一些主要的策略: 1. 模型结构优化 网络剪枝:移除模型中不重要的神经元或连接,减少模型复杂度。 模型精…

大模型lora微调中,rank参数代表什么,怎么选择合适的rank参数

在大模型的LoRA(Low-Rank Adaptation)微调中,rank参数(秩)是一个关键的超参数,它决定了微调过程中引入的低秩矩阵的维度。具体来说,rank参数r表示将原始权重矩阵分解成两个低秩矩阵的维度&#…

突破传统,实时语音技术的革命。Livekit 开源代理框架来袭

🚀 突破传统,实时语音技术的革命!Livekit 开源代理框架来袭! 在数字化时代,实时通信已成为我们日常生活的一部分。但你是否曾想象过,一个能够轻松处理音视频流的代理框架,会如何改变我们的沟通方式?今天,我们就来一探究竟! 🌟 什么是 Livekit 代理框架? Live…

从零开始搭建互联网医院系统:技术与案例解析

随着信息技术的飞速发展和人们对医疗服务需求的增加,互联网医院逐渐成为医疗服务的重要模式。本文将详细介绍从零开始搭建互联网医院系统的关键技术和具体案例,帮助读者理解如何构建一个高效、可靠的互联网医院系统。 一、互联网医院系统的核心技术 1…

ESLint: Delete `␍`(prettier/prettier)解决问题补充

如果你是克隆的,参考这位大佬的文章 vue.js - Delete ␍eslint(prettier/prettier) 错误的解决方案 - 个人文章 - SegmentFault 思否 如果你是个人在本地实现,且改为 仍旧报错,我解决的方案: 改为,同时勾选和我配置一…

Error:sql: expected 1 arguments, got 2

一 背景 在测试一个API接口时,看到日志里面突然抛出一个错误:Error:sql: expected 1 arguments, got 2 看了下,对应的表里面是有相关数据的,sql语句放在mysql里面执行也是没问题!那奇了怪了,为啥会产生这样…

TensorFlow系列:第二讲:准备工作

1.创建项目,选择虚拟环境 项目结构如下: data中的数据集需要提前准备好,数据分为测试集,训练集和验证集。以下是数据集的下载平台:kaggle 2.随便选择一个和水果相关的数据集,下载到本地,导入的项…

ARM裸机:一步步点亮LED(汇编)

硬件工作原理及原理图查阅 LED物理特性介绍 LED本身有2个接线点,一个是LED的正极,一个是LED的负极。LED这个硬件的功能就是点亮或者不亮,物理上想要点亮一颗LED只需要给他的正负极上加正电压即可,要熄灭一颗LED只需要去掉电压即可…

字节码编程javassist之生成带有注解的类

写在前面 本文看下如何使用javassist生成带有注解的类。 1:程序 测试类 package com.dahuyou.javassist.huohuo.cc;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import ja…

JVM原理(二四):JVM虚拟机锁优化

高效并发是从JDK 5升级到JDK 6后一项重要的改进项,HotSpot虛 拟机开发团队在这个版本上花费了大量的资源去实现各种锁优化技术,如适应性自旋( Adaptive Spinning)、锁消除( Lock Elimination)、锁膨胀(Lock Coarsening)、轻量级锁(Lightweight Locking)、…

了解PPO算法(Proximal Policy Optimization)

Proximal Policy Optimization (PPO) 是一种强化学习算法,由 OpenAI 提出,旨在解决传统策略梯度方法中策略更新过大的问题。PPO 通过引入限制策略更新范围的机制,在保证收敛性的同时提高了算法的稳定性和效率。 PPO算法原理 PPO 算法的核心…

LAMP万字详解(概念、构建步骤)

目录 LAMP Apache 起源 主要特点 软件版本 编译安装httpd服务器 编译安装的优点 操作步骤 准备工作 编译 安装 优化执行路径 添加服务 守护进程 配置httpd 查看 Web 站点的访问情况 虚拟主机 类型 部署基于域名的虚拟主机 为虚拟主机提供域名解析&#xff…

ESP32的I2S引脚及支持的音频标准使用说明

ESP32 I2S 接口 ESP32 有 2 个标准 I2S 接口。这 2 个接口可以以主机或从机模式,在全双工或半双工模式下工作,并且可被配置为 8/16/32/48/64-bit 的输入输出通道,支持频率从 10 kHz 到 40 MHz 的 BCK 时钟。当 1 个或 2 个 被配置为主机模式…

db期末复习自用[应试向 附习题]

第一章 数据库系统实现整体数据的结构化,主要特征之一,是db区别于文件系统的本质区别。 数据库系统三个阶段:人工、文件、数据库系统。 数据库管理系统的功能:数据库定义、操纵 、(保护、存储、维护)、数…