Python设计模式中的创建型工厂模式

 更新时间:2022年02月15日 09:04:00   作者:范桂飓  
这篇文章主要介绍了Python设计模式中的创建型工厂模式,工厂模式即Factory Pattern,是提供创建对象的最佳方式,下文小编介绍Python工厂模式的相关资料,需要的朋友可以参考一下

一、工厂模式(Factory Pattern)

工厂模式(Factory Pattern),提供了一种实例化(创建)对象的最佳方式。

在工厂模式中,首先定义了一个抽象的工厂类(class Factory),并且在该工厂类中定义了提供了一个通用的、用于实例化对象的 Interface(接口)函数。然后当 Client 想要实例化某个具体的类的对象时,只需要将需求告诉工厂类即可,由工厂类按需求去完成对象的实例化并返回。而 Client 作为调用者,则无需知道对象实例化的任何细节,这意味着任意的 Client 都无需要考虑根据对象的实例化细节来调整自身的代码。

例如:当我们需要购买一批电脑,只要把我们的需求告诉电脑工厂,电脑工厂就会帮我们把这批电脑做好,而不用我们自己去做这个电脑的,也不用我们自己去知道这个电脑是怎么做出来的,这就是工厂模式。

工厂模式带来的好处就是帮助我们把对象的实例化部分抽取了出来,目的是降低系统中代码耦合度,并且增强了系统的扩展性。是一种解耦思想的实践。

二、应用场景

  • Multi-Drivers(多驱动架构)

三、编码示例

1、简单工厂模式

简单工厂模式,只是做了一层简单的封装,将不同对象的实例化操作都单独放到了一个工厂类中。

当我们需要实例化某个对象时,只需把我们的需求告诉简单工厂类,然后由这个简单工厂类根据我们的需求去创建对应的对象即可。适用于简单的业务场景。

优点: 简单工厂模式可以根据需求,动态生成使用者所需类的对象,而使用者不用去知道怎么创建对象,使得各个模块各司其职,降低了系统的耦合性。

缺点: 扩展性差,违背了开闭原则(开闭原则指的是:软件实现应该对扩展开放,对修改关闭)。新增产品时,需要修改简单工厂类的代码。

实体角色:

  • 产品的抽象类
  • 具体的产品子类
  • 简单工厂类
import abc

# 产品的抽象类
class Productor(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def product(self, car):
        pass
        
# 更具体的某个产品类,是产品抽象类的子类
class Xiaomi(Productor):
    """
    小米手机
    """
    def product(self, price):
        return f"制造一部小米手机,售价{price}元"
        
    def __repr__(self):
        return f"Xiaomi,{id(self)}" 
    
# 更具体的某个产品类,是产品抽象类的子类
class Huawei(Productor):
    """
    华为手机
    """
    def product(self, price):
        return f"制造一部华为手机,售价{price}元"
        
    def __repr__(self):
        return f"Huawei,{id(self)}" 
    
# 简单工厂类
class PhoneBrandFactory:
    """
    简单工厂
    """
    def create_productor(self, brand):
        if brand == "Xiaomi":
            return Xiaomi()
        if brand == "Huawei":
            return Huawei()
        else:
            raise TypeError(f"没有名为{brand}的手机生产商。")
        

if __name__ == "__main__":
    # 通过简单工厂类提供的接口函数来获得某个具体的产品类的对象
    Xiaomi = PhoneBrandFactory().create_productor("Xiaomi")
    Huawei = PhoneBrandFactory().create_productor("Huawei")
    print(Xiaomi)
    print(Huawei)
    print(Xiaomi.product(2999))
    print(Huawei.product(5999))

2、工厂方法模式

工厂方法模式,工厂类派生了任意个子工厂类,每个子工厂类对应一个具体的产品类,则某个产品类的对象的实例化就交由这个子工厂类来完成。

工厂方法模式是简单工厂模式的改进,当我们需要扩展一个新产品时,只需要扩展一个新的子工厂类即可,而不用去修改工厂类原有的代码,这样就符合了开闭原则。

优点: 扩展性好,符合了开闭原则。新增一种产品时,只需增加改对应的产品类和对应的工厂子类即可。同时,也使得每个产品类和对应的工厂子类符合了单一职责原则,每个工厂只负责一种产品,而不是由一个工厂去生成所有商品。

缺点: 当我们新增产品时,还需要提供对应的工厂类,系统中类的个数将会成倍增加,相当于增加了系统的复杂性。

实体角色:

  • 产品的抽象类
  • 具体的产品子类
  • 工厂类
  • 具体的工厂子类
import abc

# 产品的抽象类
class Productor(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def product(self, car):
        pass
        
# 更具体的某个产品类,是产品抽象类的子类
class Xiaomi(Productor):
    """
    小米手机
    """
    def product(self, price):
        return f"制造一部小米手机,售价{price}元"
        
    def __repr__(self):
        return f"Xiaomi,{id(self)}" 
    
# 更具体的某个产品类,是产品抽象类的子类
class Huawei(Productor):
    """
    华为手机
    """
    def product(self, price):
        return f"制造一部华为手机,售价{price}元"
        
    def __repr__(self):
        return f"Huawei,{id(self)}" 
    
# 工厂类
class PhoneBrandFactory(metaclass=abc.ABCMeta):
    """
    抽象工厂
    """
    @abc.abstractmethod
    def create_productor(self, brand):
        pass
    
# 具体产品对应的子工厂类
class XiaomiFactory(PhoneBrandFactory):
    def create_productor(self):
        return Xiaomi()
    
# 具体产品对应的子工厂类
class HuaweiFactory(PhoneBrandFactory):
    def create_productor(self):
        return Huawei()


if __name__ == "__main__":
    # 由这个子工厂类来完成对应的某个产品类的对象实例化
    Xiaomi = XiaomiFactory().create_productor()
    Huawei = HuaweiFactory().create_productor()
    print(Xiaomi)
    print(Huawei)
    print(Xiaomi.product(2999))
    print(Huawei.product(5999))

3、抽象工厂模式

抽象工厂模式,又是工厂方法模式的改进。工厂方法模式解决的是生产不同品牌的同一类型的电脑,而抽象工厂模式解决的是生产不同品牌的多种类型的电脑。

比如,工厂方法模式中的电脑工厂只能生产老式的台式电脑,而如果现在需要生产台式电脑,笔记本电脑,平板电脑等多个种类的电脑的话,那么工厂方法模式就不太方便了。而抽象工厂模式可以解决电脑工厂生产多个种类电脑的问题,也就是解决一个工厂生产多种类型的产品的问题。

如果我们需要台式电脑,又需要笔记本电脑,要多种产品时,工厂方法模式无法满足我们的需求;而抽象方法模式,提前在抽象工厂中,定义好了可能需要的多种产品,比如:台式电脑,笔记本电脑,平板电脑等,当有需求的时候,我们只需要创建相关子类和相关子工厂类即可。

优点: 抽象工厂类创建了多个类型的产品,当有需求时,可以创建相关子产品类和子工厂类来获取。也就是可以满足生产不同品牌的不同类型的电脑。

缺点: 扩展新种类产品时困难。抽象工厂模式需要我们在工厂抽象类中提前确定了可能需要的产品种类,以满足不同品牌的多种产品的需求。但是如果我们需要的产品种类并没有在工厂抽象类中提前确定,那我们就需要去修改工厂抽象类了,而一旦修改了工厂抽象类,那么所有的工厂子类也需要修改,这样显然扩展不方便。

实体角色:

  • 产品功能特性抽象类
  • 具体的产品功能特性子类
  • 产品的抽象类
  • 具体的产品子类
  • 抽象工厂类
import abc

# 产品功能特性抽象类
class PhoneShell(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def shell(self):
        pass
   
class Cpu(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def cpu(self):
        pass
     
class OS(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def system(self):
        pass
    
# 具体的产品功能特性类
class SmallShell(PhoneShell):
    @property
    def shell(self):
        return "小屏幕"

class BigShell(PhoneShell):
    @property
    def shell(self):
        return "大屏幕"
    
class SnapDragonCpu(Cpu):
    @property
    def cpu(self):
        return "骁龙cpu"
        
class AppleCpu(Cpu):
    @property
    def cpu(self):
        return "苹果cpu"
        
class Android(OS):
    @property
    def system(self):
        return "安卓系统"    
    
class IOS(OS):
    @property
    def system(self):
        return "IOS系统"
    
# 产品的抽象类
class ProductPhone:
    
    def __init__(self, factory):
        self.factory = factory()
        
    def product(self):
        self.shell = self.factory.product_shell()
        self.cpu = self.factory.product_cpu()
        self.OS = self.factory.product_system()
    
    def show_info(self):
        print(f"{self.factory}", f"配置信息:{self.shell.shell}, {self.cpu.cpu}, {self.OS.system}")
            
# 具体的产品子类
class XiaomiFactory(PhoneFactory):
    def product_shell(self):
        return BigShell()
    
    def product_cpu(self):
        return SnapDragonCpu()
    
    def product_system(self):
        return Android()
    
    def __repr__(self):
        return "小米手机,售价2999!"
        
class IphoneFactory(PhoneFactory):
    def product_shell(self):
        return SmallShell()
    
    def product_cpu(self):
        return AppleCpu()
    
    def product_system(self):
        return IOS()
    
    def __repr__(self):
        return "苹果手机,售价8999!"
    
# 抽象工厂类
class PhoneFactory(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def product_shell(self):
        pass
    
    @abc.abstractmethod
    def product_cpu(self):
        pass
    
    @abc.abstractmethod
    def product_system(self):
        pass 

        
if __name__ == "__main__":
    xiaomi = ProductPhone(XiaomiFactory)
    xiaomi.product()
    xiaomi.show_info()
    
    iphone = ProductPhone(IphoneFactory)
    iphone.product()
    iphone.show_info()

到此这篇关于Python设计模式中的创建型工厂模式的文章就介绍到这了,更多相关Python工厂模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python飞机大战pygame游戏背景设计详解

    python飞机大战pygame游戏背景设计详解

    这篇文章主要介绍了python飞机大战pygame游戏背景设计,结合实例形式详细分析了Python使用pygame模块设计游戏背景相关原理、流程与实现技巧,需要的朋友可以参考下
    2019-12-12
  • python使用gdal对shp读取,新建和更新的实例

    python使用gdal对shp读取,新建和更新的实例

    这篇文章主要介绍了python使用gdal对shp读取,新建和更新的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03
  • Django使用模板后无法找到静态资源文件问题解决

    Django使用模板后无法找到静态资源文件问题解决

    这篇文章主要介绍了Django使用模板后无法找到静态资源文件问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • Python isalpha()函数的具体使用方法详解

    Python isalpha()函数的具体使用方法详解

    这篇文章主要介绍了Python isalpha()函数的具体使用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Python Beautiful Soup模块使用教程详解

    Python Beautiful Soup模块使用教程详解

    Beautiful Soup 简称 BS4(其中 4 表示版本号)是一个 Python 中常用的页面解析库,它可以从 HTML 或 XML 文档中快速地提取指定的数据,这篇文章主要介绍了Python Beautiful Soup模块的使用
    2023-02-02
  • Python 调用 Outlook 发送邮件过程解析

    Python 调用 Outlook 发送邮件过程解析

    这篇文章主要介绍了Python 调用 Outlook 发送邮件过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-08-08
  • python logging重复记录日志问题的解决方法

    python logging重复记录日志问题的解决方法

    python的logging模块是python使用过程中打印日志的利器,下面这篇文章主要给大家介绍了关于python logging重复记录日志问题的解决方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-07-07
  • 关于Python Socket编程的要点详解

    关于Python Socket编程的要点详解

    Socket是网络编程的一个抽象概念,通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地址和端口号,再指定协议类型即可,这篇文章主要给大家介绍了关于Python Socket编程的相关资料,需要的朋友可以参考下
    2021-08-08
  • Python自动发送邮件的方法实例总结

    Python自动发送邮件的方法实例总结

    这篇文章主要介绍了Python自动发送邮件的方法,结合实例形式总结分析了Python使用smtplib和email模块发送邮件的相关使用技巧与操作注意事项,需要的朋友可以参考下
    2018-12-12
  • django中使用POST方法获取POST数据

    django中使用POST方法获取POST数据

    这篇文章主要介绍了django中使用POST方法获取POST数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08

最新评论