网络编程
位置:首页>> 网络编程>> Python编程>> Python设计模式中的创建型工厂模式

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

作者:范桂飓  发布时间:2023-05-09 17:47:02 

标签:Python,设计,模式,工厂,模式

一、工厂模式(Factory Pattern)

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

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

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

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

二、应用场景

  • Multi-Drivers(多驱动架构)

三、编码示例

1、简单工厂模式

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

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

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

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

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

实体角色:

  • 产品的抽象类

  • 具体的产品子类

  • 简单工厂类

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、工厂方法模式

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

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

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

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

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

实体角色:

  • 产品的抽象类

  • 具体的产品子类

  • 工厂类

  • 具体的工厂子类

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()

来源:https://is-cloud.blog.csdn.net/article/details/122921015

0
投稿

猜你喜欢

  • 自执行函数:自动执行的函数。它在被解释时就已经在运行了。一般函数都是在被调用时才会执行的。 自执行函数的一般格式:(function() {
  • 1.怎么样查看数据库字符集 [A]数据库服务器字符集select * from nls_database_parameters,其来源于pr
  • 现在同类型的网站数不胜数,网站的功能或服务日趋同质化,大的方面看不出什么差别,差别就体现在细节上。“窥斑见豹”,细节成为网站最有力的表现形式
  • 本文介绍了网页中插入视频播放的代码全集:有avi格式的视频,mpg格式,smi格式,rm格式,wmv格式,wma格式,Windows Med
  • 我们在用python进行程序开发的时候,很多时候我们需要检测一下当前的变量的数据类型。比如需要在使用字符串操作函数之前先检测一下当前变量是否
  • 关于书写习惯,遵循曾经总结过的风格标准,现在一点都没有变。并且近来翻看高手作品,横向连排似乎在大产品项目中逐渐成为主流,个人认为如此维护效率
  • (1) 展示了ASP * 站设计的一些最基本的方法,相信通过实践各位对ASP已经有了最基本的了解,本篇在答复大家所提问题的同时,将进一步介绍
  • PHP保存session默认的是采用的文件的方式来保存的,这仅仅在文件的空间开销很小的windows上是可以采用的,但是如果我们采用uinx
  • 在ASP的实际操作中,总会发生这样的情况,如在银行,从我的帐户往费文华的帐户划款,我的帐户显示已经划出,但因银行的系统出现故障,导致费文华帐
  • 列表对象pop()方法的使用pop() 方法用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。语法:verse.pop(in
  • 将opencv中haarcascade_frontalface_default.xml文件下载到本地,我们调用它辅助进行人脸识别。识别图像中
  • 前言: 这篇文章主要介绍RMAN的常用方法,其中包含了作者一些自己的经验,里面的实验也基本全在WIN 2K和ORACLE 8.1.6环境下测
  • 今天不小心又点了收藏夹里Google的新首页风格的地址,赫然发现又变了!从这个页面上线以来,偶尔会去看看,短短一年的时间,已经变换了至少三次
  • 1.      void ellipse(InputOutputArray img, Po
  • 八卦为先八卦是种优良品质,特别是用在技术上时。来看几个Reset CSS的八卦问题吧:你知道世界上第一份reset.css在哪么?* { m
  • 本文实例讲述了php+mysqli数据库连接的两种方式。分享给大家供大家参考。具体如下:这里讲述mysqli数据库连接两种方式比较,即面向对
  • 又是一年春来到,看各大网站的新年Logo也成为了我们必不可少的新年餐点,为此,我们特别整理了部分网站的新年Logo秀,如果你看到了更加有意思
  • 本文实例讲述了PHP依赖注入原理与用法。分享给大家供大家参考,具体如下:引言依然是来自到喜啦的一道面试题,你知道什么是依赖注入吗?依赖注入(
  • 本书的作者Douglas Crockford是JavaScript开发社区最知名的权威,JavaScript的发明人Brendan Eich
  • TensorFlow是Google公司2015年11月开源的第二代深度学习框架,是第一代框架DistBelief的改进版本. TensorF
手机版 网络编程 asp之家 www.aspxhome.com