Python工厂方法介绍及应用优化

【python高级】设计模式、类工厂、对象工厂 最近试着读Design pattern, 不过有些概念实在太抽象了, 整理一下自己所学抽象工厂的精神,就是要有abstract class(not implement),而所有不同种类的对象,都是继承这个abstract class,但是使用者只知道interface的接口就好。 阅读详情


前言

本文简单介绍设计模式中的工厂方法的实现方式及应用
文中所引用的模块及需要注意的事项:
1、python标准库中的Typing模块及其子类Callable,此模块用于在声明变量时同时声明其变量类型。需要对变量类型的声明有一定了解。
2、python标准库中的abc模块abstractmethod装饰器,用于声明抽象类
3、工厂方法是对编码方式的一种提升方式,你可以通过自己的方式来随意的创建类及实例,但无规矩不成方圆,想要方便的调试代码减少bug及方便自己阅读或想方便别人同你合作,就要不断尝试规范自己的代码
4、对可变参数的打包及解包有一定了解


一、工厂方法简单介绍

通过一个简单例子来作说明:假如有三个人,小明,小明的爸爸及小明的老师,小明每天需要按时去学校上学,小明的爸爸每天需要去送小明上学,小明的老师在学校等待小明来学校报到,如何通过程序来描述三个人的行为?同时抽象出这种行为后可以扩展下,可以定义某名同学去的上学,送其上学的是其他人,在学校等待报到的有可能是其他老师,如何创建相应的实例来描述这些行为?

1、 统计信息

将三个人的信息进行分析,找到三个人身份的共同点及不同点,三个人各自不同点有其名字及身份,相同点是三个人作为不同身份的人都有其相应的职责,学生需要上学,爸爸需要送孩子上学,老师需要学生来学校报到,抽离出所用的信息:

people_data = {
        'people': [
            {'name': 'XiaoMing', 'identity': 'Student'},
            {'name': 'DaMing', 'identity': 'Parent'},
            {'name': 'TeacherWang', 'identity': 'Teacher'}
        ]
    }

我们通过所统计的个体信息进行实例创建,三个人作为人的个体都有名字及身份,可抽象出一个父类人,再从父类中继承作为人的属性,根据不同身份的职责扩展出其子类(学生,爸爸,老师),在子类下定义不同身份下的职责。

2、简单实现

from abc import abstractmethod


# 创建工厂类的抽象类
class Person:
    def __init__(self, name, identity):
        self.name = name
        self.identity = identity

    @abstractmethod
    def action(self):
        """Person action"""

    def __str__(self):
        return f'{self.name} {self.identity}'


# 创建工厂类的具体类
class Student(Person):

    # def __init__(self, name, identity):
    #     super().__init__(name, identity)

    def action(self) -> None:
        print(f'{self.name} is going to school')


# 创建工厂类的具体类
class Parent(Person):

    # def __init__(self, name, identity):
    #     super().__init__(name, identity)

    def action(self) -> None:
        print(f'{self.name} is sending children to school')


# 创建工厂类的具体类
class Teacher(Person):

    # def __init__(self, name, identity):
    #     super().__init__(name, identity)

    def action(self) -> None:
        print(f'{self.name} is waiting student to school')


# 此处为简单的工厂实现但在大数据量的情况下违背了对扩展开放对修改封闭的原则,业务逻辑改动量较大
if __name__ == '__main__':
    # 声明要创建的类的数据
    peopleData = {
        'people': [
            {'name': 'XiaoMing', 'identity': 'Student'},
            {'name': 'DaMing', 'identity': 'Parent'},
            {'name': 'TeacherWang', 'identity': 'Teacher'}
        ]
    }
    insPersons = []

    for item in peopleData['people']:
        if item['identity'] == 'Student':
            insPersons.append(Student(**item))
        elif item['identity'] == 'Parent':
            insPersons.append(Parent(**item))
        elif item['identity'] == 'Teacher':
            insPersons.append(Teacher(**item))
    for item_person in insPersons:
        print(item_person)
        item_person.action()

最常想到的创建类的方式或许通过以上或类似的方式,从以上示例中我们可以拆分出三个业务模块,
1、抽象类声明,如上示例中的Person类,用于概括所要创建类的共同点
2、具体类,即示例中的Student,Parent,Teacher子类,其包含了各自的方法(职责)
3、工厂方法,即示例中根据信息创建实例的For语句

如果后面有爷爷来送孩子上学,我们需要有哪些改动?但考虑到以后代码的可维护性及扩展性可以怎样优化?

如果需要添加子类(如添加爷爷类),那么需要在具体类里添加子类及修改工厂方法,代码设计有一个原则‘对扩展开放,对修改封闭’,即工厂方法应当只关注于创建实例的接口并不关心实例应当如何实现,再回顾下示例中创建实例的方法:其中For 循环其实包含了代码的坏味道,其代码是工厂方法的实现,但在用户调用时已经参与到了工厂方法中,最好的方式是用户调用时只调用接口并不能修改工厂方法

    for item in peopleData['people']:
        if item['identity'] == 'Student':
            insPersons.append(Student(**item))
        elif item['identity'] == 'Parent':
            insPersons.append(Parent(**item))
        elif item['identity'] == 'Teacher':
            insPersons.append(Teacher(**item))

二、进一步优化

我们尝试对工厂方法进行进一步优化,将工厂方法对客户进行封闭,这样保证用户只关心调用,这样才能更符合‘对扩展开放,对修改封闭’的原则

在这里我们将会创建一个新的python模块,在此模块中对工厂方法进行封装,并对外开放接口。在这里我们通过在工厂方法里添加引用 类型字典的方式并创建为字典添加引用类型的方法Resgister,Unregister进行类型的添加及注销,并开放Create方法方便客户进行调用来生成实例,这样客户只能通过Register或Unregister方式来扩展工厂方法但并不会直接修改其代码,保证了对修改封闭的原则的同时也对外保证了对扩展开放。

具体实现

代码实现将代码分为了三个部分,一个是抽象类及具体类声明部分Person_AbstractClass.py,第二部分为工厂方法部分Person_FactoryMethod.py,第三部分是用户调用部分Person_FactoryRealize.py

1、抽象类及具体类部分

此处与上示例的声明部分相同
Person_AbstractClass.py

from abc import abstractmethod


# 创建工厂类的抽象类
class Person:
    def __init__(self, name, identity):
        self.name = name
        self.identity = identity

    @abstractmethod
    def action(self):
        """Person action"""

    def __str__(self):
        return f'{self.name} {self.identity}'


# 创建工厂类的具体类
class Student(Person):

    # def __init__(self, name, identity):
    #     super().__init__(name, identity)

    def action(self) -> None:
        print(f'{self.name} is going to school')


# 创建工厂类的具体类
class Parent(Person):

    # def __init__(self, name, identity):
    #     super().__init__(name, identity)

    def action(self) -> None:
        print(f'{self.name} is sending children to school')


# 创建工厂类的具体类
class Teacher(Person):

    # def __init__(self, name, identity):
    #     super().__init__(name, identity)

    def action(self) -> None:
        print(f'{self.name} is waiting student to school')

2、工厂方法的封装

Person_FactoryMethod.py

from typing import Callable, Any
from Person_AbstractClass import Person

# 创建存储类型的字典,根据‘对扩展开放,对扩展封闭’的原则,在以后需要扩展Person子类时此模块不需要再更改,
# 只需要调用Register,Unregister注册或注销即可
# 关于Callable后面的省略号作用为忽略参数声明,但指定返回为Person类型
person_create_function: dict[str, Callable[..., Person]] = {}


# 向person_create_function 字典注册类型, 通过设置Callable返回基类类型Person就可以在使用register时返回子类类型
def register(identity: str, creation_function: Callable[..., Person]) -> None:
    person_create_function[identity] = creation_function


# 向person_create_function 字典注销类型
def unregister(identity: str) -> None:
    person_create_function.pop(identity, None)


# 通过存储数据的字典来创建实例
def create(args: dict[str, Any]) -> Person:
    the_args = args.copy()
    identity = the_args['identity']

    create_function = person_create_function[identity]
    return create_function(**the_args)

3、用户调用接口

Person_FactoryRealize.py

from Person_AbstractClass import Person, Student, Parent, Teacher
from Person_FactoryMethod import register, unregister, create


def main():
    """
    the main function for modify the factory method and create the instance
    :return: None
    """

    people_data = {
        'people': [
            {'name': 'XiaoMing', 'identity': 'Student'},
            {'name': 'DaMing', 'identity': 'Parent'},
            {'name': 'TeacherWang', 'identity': 'Teacher'}
        ]
    }

    # 通过Register方法来向工厂类中注册所需要使用的类型
    register('Student', Student)
    register('Parent', Parent)
    register('Teacher', Teacher)

    # 通过数据参数来创建类实例
    for item_person in people_data['people']:
        ins_person = create(item_person)
        print(ins_person)
        ins_person.action()


if __name__ == '__main__':
    main()

总结

工厂方法的创建及对’对扩展开放,对修改封闭’原则的优化部分结束

生产过程仿真:用Python重现工厂的智慧与精细化 通过仿真技术,工厂可以在实际生产之前,模拟出不同生产场景,帮助企业提前识别潜在问题,优化生产计划,从而提高整体运作效率。仿真模型可以帮助企业在没有实际生产的情况下,模拟出生产过程中的各类因素,如设备故障、工艺变动、资源调度等,从而预测系统的行为和性能。此外,我们还可以通过仿真模型进行不同生产方案的对比,如增加设备数、调整工序顺序、引入自动化等,优化整个生产过程,达到提高效率、降低成本的目的。接下来,我将展示一个简化的生产过程仿真案例,通过Python模拟一个简单的生产线,分析其中的瓶颈,进而优化生产效率。 阅读详情

相关推荐

16、设计模式与性能优化:抽象工厂、适配器与性能瓶颈识别

本文探讨了抽象工厂模式和适配器模式的应用场景、设计思路及Python实现方法,并详细阐述了性能优化的相关技术,包括性能瓶颈的识别与优化策略。通过游戏开发中的具体案例,如角色配件创建与接口不兼容问题,展示了设计模式的实际应用。此外,结合‘黄金狩猎’场景,介绍了提高运行时性能的方法,旨在提升代码可维护性和应用程序的整体性能。

kkk56的博客 70

Python设计模式之创建型-工厂方法模式(Factory Method)

工厂方法(Factory Method)模式是一种常见的创建型设计模式,它通过定义一个创建对象的接口,但是它将对象的创建延迟到子类中实现,每个具体子类都可以创建自己特定的对象。在前面的文章中对简单工厂做了详细介绍,工厂方法和简单工厂的区别在于,简单工厂模式只有一个工厂,工厂方法模式对每一个产品都有相应的工厂。在本文中,我们将介绍工厂方法模式的概念、作用、特点和使用方法,以及使用4个Python代码示例分别实现工厂方法模式,包括通过创建不同类型的动物、解析不同类型的文本文件来演示该模式的应用。

SteveRocket's-Blog 943

贝塞尔曲线生成原理及python实现

贝塞尔曲线(Bezier Curve)是一类通过控制点来生成平滑曲线的数学方法。它最早由法国工程师皮埃尔·贝塞尔(Pierre Bézier)在20世纪60年代提出,广泛应用于计算机图形学、动画、路径规划等领域。贝塞尔曲线的一个重要特点是,它通过一组控制点来定义曲线的形状,其中最常见的是二次贝塞尔曲线和三次贝塞尔曲线。控制点:曲线的形状是由一组控制点决定的,控制点的数目影响贝塞尔曲线的阶数。平滑性:贝塞尔曲线是连续且光滑的,适合用于插值和平滑路径规划。局部性。

闲人编程的博客 1245

【二】python工厂模式

在面向对象编程中,术语“工厂”表示一个负责创建替他类型对象的类。通常情况下,作为一个工厂的类有一个对象以及与它关联的多个方法。客户端使用某些参数调用此方法,之后,工厂会据此创建所需类型的对象,然后将它们返回给客户端。工厂模式在实际的应用场景举例:假如有一个消息通知的功能,需要实现根据不同的消息内容发送到邮件、微信等渠道。我们就可以利用工厂模式来进行解耦,以后如果新增了短信等其他通知方式,就可以轻松应对,对原有代码侵入较低,可以方便的进行扩展功能。

勿忘初心方得始终 4630

瑞芯微RK3568开发板实战:Android11系统parameter.txt文件配置全解析(附常见问题排查)

本文深入解析了瑞芯微RK3568开发板在Android 11系统下parameter.txt文件的配置要点与实战技巧。作为BootLoader启动阶段的核心蓝图,该文件决定了硬件初始化、分区布局及电源管理。文章详细拆解了身份标识、GPIO控制(PWR_HLD)、命令行参数及分区表等关键字段的配置逻辑,并针对RK3568平台与Android 11特性提供了专项适配策略,最后附带了启动失败、分区异常等常见问题的深度排查方法。

php55的博客 897

PX4自定义uORB消息与MAVLink消息映射实战:从飞控到QGC地面站完整流程解析

本文详细解析PX4飞控中自定义uORB消息与MAVLink消息映射的完整流程,涵盖从飞控内部消息定义、MAVLink消息创建到QGC地面站接收显示的全链路实践。重点介绍如何使用mavlink inspector工具进行调试,解决版本兼容性和多实例消息处理等常见问题,为无人机开发者提供可靠的实时数据监控方案。

ll5678的博客 1068

python设计模式:工厂模式

在面向对象编程中,术语“工厂”表示一个负责创建其他类型对象的类。通常情况下,作为一个工厂的类有一个对象以及与它关联的多个方法。客户端使用某些参数调用此方法,之后,工厂会据此创建所需类型的对象,然后将它们返回给客户端。

夏末蝉未鸣的博客 3965

KEGG两类报错--①No gene can be mapped--②URL ‘https://rest.kegg.jp/link/hsa/pathway‘…

版本问题,重新安装一下clusterProfiler包。网络问题,可以等待之后再试一下(试过不是)(以上可以排除基因不存在的错误因素)

weixin_57699783的博客 2万+

Python常用模块:pathlib、passlib、joblib

工厂方法就是提供一个方法,这个方法用于返回一类相关对象的其中一个对象。将一组相关的对象封装到一个方法中的好处就是在创建对象时只需要调用同一个方法即可,这样功能更加内聚,当需要修改创建对象时只需要修改这一处即可。如果不使用工厂方法,那么创建对象将会散落在代码的各个角落,修改起来容易遗漏,也比较麻烦。工厂方法的好处就是:高内聚,易维护。

人不风流枉少年 1067

利用Nginx反向代理实现GitLab自定义域名的高效配置

本文详细介绍了如何利用Nginx反向代理实现GitLab自定义域名的高效配置。通过统一域名管理、性能优化和安全加固,提升GitLab的访问效率和安全性。文章包含前期准备、GitLab基础配置、Nginx反向代理设置及常见问题排查,帮助开发者快速完成部署。

weixin_28834169的博客 165

将Apollo高精地图中的车道线叠加在多种导航地图上

本文介绍了将Apollo高精地图车道线叠加到普通导航地图的技术方案。高精地图具备厘米级车道精度和丰富的语义信息,叠加可实现可视化验证、调试分析和数据对比等功能。核心技术包括坐标系统转换(UTM/WGS84/BD09/GCJ02)和数据处理流程,通过Python脚本完成Apollo地图解析、坐标批量转换和多格式输出。文章详细提供了环境准备、工作目录创建和坐标转换脚本等操作步骤,实现了高精地图数据在OpenStreetMap、百度地图和高德地图上的可视化展示。

Hi20240217的博客 1336

Python编程:工厂模式

工厂模式是面向对象设计中最常用的创建型模式之一,它提供了一种创建对象的最佳方式。

倔强老吕的博客 619

脱壳--02.exe

程序开始 使用OD打开程序 发现无法利用esp定律 程序直接运行 查找模块间调用 随便找到一个函数的调用 发现是FF15方式调用 所以是vs的程序 vs程序大致分成两种 vs20xx (特征函数:GetSystemTimeAsFileTime)和 vc++6.0(特征函数:GetVersion) 通过链接器版本 发现是vc6.0 直接在GetVersion上下断点 重新运行程序 断点断下 返回到调用处 vc6.0和易语言的第一个CALL都是GetVers...

weixin_45012273的博客 1113

工厂方法:pybind11多态对象创建

在混合C++和Python的开发场景中,经常遇到这样的困境:C++代码定义了丰富的多态类层次结构,但Python端却难以灵活地创建这些对象。传统的构造函数绑定方式在面对私有构造函数、复杂初始化逻辑或需要运行时决策的场景时显得力不从心。 **读完本文,你将掌握:** - pybind11工厂方法的核心机制与使用场景 - 多态对象创建的三种高级模式 - 工厂方法与虚函数trampoline的完美结合...

gitblog_00757的博客 995

23、微波电路中的过孔、过孔围栏与接地焊盘建模分析

本文详细分析了微波电路设计中过孔、过孔围栏及接地焊盘的建模与优化方法。探讨了过孔模型的发展及其电感与电容特性,通过场求解器和集总元件模型提高建模精度。此外,分析了过孔隔离围栏在改善信号隔离中的作用,并通过2.5D和3D电磁仿真验证其效果。最后,研究了接地焊盘中过孔布局对电路稳定性的影响,提出了优化过孔位置以消除谐振和杂散振荡的方法。文章为微波电路设计提供了重要的理论支持和实践指导。

convnet3designer的博客 164

使用 MATLAB/Simulink 构建一个基于PID控制的直流电机速度调节系统模型

直流电机(DC Motor)因其结构简单、成本低廉、易于控制等特点,广泛应用于各种工业自动化和家用电器中。PID控制器作为最常用的控制策略之一,在直流电机的速度调节系统中具有重要应用价值。通过合理调整比例(P)、积分(I)、微分(D)三个参数,可以实现对电机速度的精确控制。本教程将带你使用构建一个基于PID控制的直流电机速度调节系统模型,涵盖电机模型构建、PID控制器设计、系统仿真与调试等多个方面。本文介绍了如何使用构建一个基于PID控制的直流电机速度调节系统模型。

amy_mhd的博客 217

Python 设计模式全解析:实战应用与优化

设计模式是构建高质量软件的基础工具。通过理解和应用上述设计模式,我们可以编写出更加灵活、可扩展且易于维护的代码。希望本文能够帮助你在 Python 开发中更有效地运用这些模式,并根据具体需求进行适当的优化。```

2501_90727689的博客 360

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

抽象工厂:pybind11跨平台对象构建

你是否曾为C++与Python之间的对象创建和生命周期管理而头疼?在跨语言编程中,如何在Python中优雅地创建和管理C++对象,同时保持类型安全和性能?pybind11的工厂模式(Factory Pattern)正是解决这一痛点的利器。 本文将深入探讨pybind11中的抽象工厂实现,展示如何通过工厂函数实现跨平台对象构建,解决复杂对象创建、多态继承和资源管理等核心问题。 ## 什么是工厂模...

gitblog_00526的博客 839

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

python | Python元类与抽象基类的实战应用

在Python的面向对象编程中,抽象基类(Abstract Base Class,简称ABC)是一个强大的特性,它为接口定义和类型检查提供了有力的支持。本文将深入探讨Python的ABC模块,剖析其实现原理,并通过实际示例展示其在工程实践中的应用。

csdn_xmj的博客 1149

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Python基础知识(十)

1. 特殊方法和运算符重载 2. 特殊属性 3. 对象的浅拷贝和深拷贝 4. 组合 5. 设计模式_工厂模式实现 6. 设计模式_单例模式实现

BucketLiu的博客 189

Python中的闭包机制深入理解与实战应用

闭包是一种特殊的函数,它能够记住并访问其所在词法作用域中的变量,即使函数是在该作用域之外执行。在Python中,闭包允许函数携带其创建时的环境信息,从而保留状态或配置。闭包是Python中强大且灵活的特性,正确使用可以大大提高代码的模块化和表达能力。理解闭包的工作原理和潜在陷阱,有助于编写更健壮和高效的代码。在实际项目中,应结合具体需求,合理选择闭包、类或其他编程结构来实现目标。

be_happy_lee的博客 386

Python设计模式

创建型模式如工厂模式和单例模式,专注于对象创建机制,提高了代码的灵活性。结构型模式包括适配器模式和装饰器模式,它们处理类和对象的组合,简化了系统结构。通过采用适当的设计模式,开发团队能够创建更加灵活和健壮的应用程序,同时降低代码的复杂性和耦合度。通过工厂模式,可以将对象的创建与使用分离,提高代码的灵活性和可维护性。在Python中,这一模式可以通过简单的回调机制实现,也可以使用更高级的事件系统。策略模式允许在运行时选择算法的行为。通过策略模式,可以轻松扩展新的算法,而不会影响现有的代码结构。

邋遢大王 368

Python实现QR码详解

本文介绍了QR码的生成原理及编码标准,使用Python实现了QR码生成工具类,并通过多个实例展示了如何应用设计模式优化代码。通过这些设计模式的组合,QR码生成代码更加模块化、灵活且易于扩展,适合应用在实际项目中。

闲人编程的博客 1991

Python基础学习第十课:SQLAlchemy ORM与Flask部署

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db' # SQLite数据库路径。app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # 关闭修改跟踪(提升性能)alias /path/to/your/app/static;app.config.from_object(config_class) # 加载配置。with app.app_context(): # Flask应用上下文。

2502_92884473的博客 489
上一篇: Python 装饰器的三种用法及使用示例
下一篇: Python 正则表达式应用,re模块
PittDing
博客等级 码龄7年 227粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值