python 实现 工厂模式

本文目录地址

本文代码地址

创建型设计模式处理对象创建相关的问题,目标是当直接创建对象(在Python中是通过__init__()函数实现的)不太方便时,提供更好的方式。
在工厂设计模式中,客户端①可以请求一个对象,而无需知道这个对象来自哪里;也就是,使用哪个类来生成这个对象。工厂背后的思想是简化对象的创建。与客户端自己基于类实例化直接创建对象相比,基于一个中心化函数来实现,更易于追踪创建了哪些对象。通过将创建对象的代码和使用对象的代码解耦,工厂能够降低应用维护的复杂度。
工厂通常有两种形式:一种是工厂方法(Factory Method),它是一个方法(或以地道的Python术语来说,是一个函数),对不同的输入参数返回不同的对象;第二种是抽象工厂,它是一组用于创建一系列相关事物对象的工厂方法。

目录

1.1 工厂方法

1.1.1应用案例

1.1.2实现

1.2抽象工厂

1.2.1现实生活的例子

1.2.2应用案例

1.2.3实现

1.3小结


1.1 工厂方法

在工厂方法模式中,我们执行单个函数,传入一个参数(提供信息表明我们想要什么),但并不要求知道任何关于对象如何实现以及对象来自哪里的细节。

1.1.1应用案例

如果因为应用创建对象的代码分布在多个不同的地方,而不是仅在一个函数/方法中,你发现没法跟踪这些对象,那么应该考虑使用工厂方法模式。工厂方法集中地在一个地方创建对象,使对象跟踪变得更容易。注意,创建多个工厂方法也完全没有问题,实践中通常也这么做,对相似的对象创建进行逻辑分组,每个工厂方法负责一个分组。例如,有一个工厂方法负责连接到不同的数据库(MySQL、SQLite),另一个工厂方法负责创建要求的几何对象(圆形、三角形),等等。
若需要将对象的创建和使用解耦,工厂方法也能派上用场。创建对象时,我们并没有与某个特定类耦合/绑定到一起,而只是通过调用某个函数来提供关于我们想要什么的部分信息。这意味着修改这个函数比较容易,不需要同时修改使用这个函数的代码。
另外一个值得一提的应用案例与应用性能及内存使用相关。工厂方法可以在必要时创建新的对象,从而提高性能和内存使用率。若直接实例化类来创建对象,那么每次创建新对象就需要分配额外的内存(除非这个类内部使用了缓存,一般情况下不会这样)。用行动说话,下面的代码(文件id.py)对同一个类A创建了两个实例,并使用函数id()比较它们的内存地址。输出中也会包含地址,便于检查地址是否正确。内存地址不同就意味着创建了两个不同的对象。

class A():
    pass

a=A()
b=A()

print(id(a)==id(b))
print(a,b)

输出

False
<__main__.A object at 0x7fbeefe5ef98> <__main__.A object at 0x7fbeefe5efd0>

注意,你执行这个代码文件看到的地址会与我看到的不一样,因为这依赖程序运行时内存的布局和分配。但结果中有一点肯定是一样的,那就是两个地址不同。在Python Read-Eval-Print Loop(REPL)模式(即交互式提示模式)下编写运行这段代码时会出现例外,但这只是交互模式特有的优化,并不常见。

1.1.2实现

数据来源可以有多种形式。存取数据的文件主要有两种分类:人类可读文件和二进制文件。人类可读文件的例子有:XML、Atom、YAML和JSON。二进制文件的例子则有SQLite使用的.sq3文件格式,及用于听音乐的.mp3文件格式。
以下例子将关注两种流行的人类可读文件格式:XML和JSON。虽然人类可读文件解析起来通常比二进制文件更慢,但更易于数据交换、审查和修改。基于这种考虑,建议优先使用人类可读文件,除非有其他限制因素不允许使用这类格式(主要的限制包括性能不可接受以及专有的二进制格式)。
在当前这个问题中,我们有一些输入数据存储在一个XML文件和一个JSON文件中,要对这两个文件进行解析,获取一些信息。同时,希望能够对这些(以及将来涉及的所有)外部服务进行集中式的客户端连接。我们使用工厂方法来解决这个问题。虽然仅以XML和JSON为例,但为更多的服务添加支持也很简单。

首先,来看一看数据文件。基于Wikipedia例子的XML文件person.xml包含个人信息(firstName、lastName、gender等),如下所示。

<persons>
     <person>
       <firstName>John</firstName>
       <lastName>Smith</lastName>
       <age>25</age>
       <address>
         <streetAddress>21 2nd Street</streetAddress>
         <city>New York</city>
         <state>NY</state>
         <postalCode>10021</postalCode>
       </address>
       <phoneNumbers>
         <phoneNumber type="home">212 555-1234</phoneNumber>
         <phoneNumber type="fax">646 555-4567</phoneNumber>
       </phoneNumbers>
       <gender>
         <type>male</type>
       </gender>
     </person>
     <person>
       <firstName>Jimy</firstName>
       <lastName>Liar</lastName>
    <age>19</age>
    <address>
      <streetAddress>18 2nd Street</streetAddress>
      <city>New York</city>
      <state>NY</state>
      <postalCode>10021</postalCode>
    </address>
    <phoneNumbers>
      <phoneNumber type="home">212 555-1234</phoneNumber>
    </phoneNumbers>
    <gender>
      <type>male</type>
    </gender>
  </person>
  <person>
    <firstName>Patty</firstName>
    <lastName>Liar</lastName>
    <age>20</age>
    <address>
      <streetAddress>18 2nd Street</streetAddress>
      <city>New York</city>
      <state>NY</state>
      <postalCode>10021</postalCode>
    </address>
    <phoneNumbers>
      <phoneNumber type="home">212 555-1234</phoneNumber>
      <phoneNumber type="mobile">001 452-8819</phoneNumber>
    </phoneNumbers>
    <gender>
 
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
工厂模式是一种常用的设计模式,它通过定义一个工厂类来创建对象实例,而不是直接在代码中创建对象实例。这种方式可以让代码更加灵活,易于维护和扩展。在 Python 中,可以使用类方法或静态方法实现工厂模式。 以下是一个示例代码: ```python class Animal: def __init__(self, name): self.name = name def speak(self): pass class Dog(Animal): def speak(self): return "Woof!" class Cat(Animal): def speak(self): return "Meow!" class AnimalFactory: @classmethod def create_animal(cls, animal_type, name): if animal_type == "dog": return Dog(name) elif animal_type == "cat": return Cat(name) else: raise ValueError("Invalid animal type") # 使用工厂类创建对象实例 dog = AnimalFactory.create_animal("dog", "Fido") cat = AnimalFactory.create_animal("cat", "Fluffy") # 调用对象实例的方法 print(dog.speak()) # 输出 "Woof!" print(cat.speak()) # 输出 "Meow!" ``` 在这个例子中,我们定义了一个 Animal 类和它的两个子类 Dog 和 Cat。Animal 类有一个实例变量 name 和一个方法 speak(),但是它的方法体为空。Dog 和 Cat 类分别重写了 Animal 类的 speak() 方法。 我们还定义了一个 AnimalFactory 工厂类,它有一个类方法 create_animal(),接收两个参数:animal_type 和 name。如果 animal_type 是 "dog",则返回一个 Dog 的实例,如果是 "cat",则返回一个 Cat 的实例。否则,抛出一个 ValueError 异常。 在主程序中,我们使用 AnimalFactory 工厂类分别创建了一个 Dog 和 Cat 的实例,并调用它们的 speak() 方法。 需要注意的是,这里使用的是类方法(classmethod)来实现工厂模式。另外,工厂类也可以使用静态方法(staticmethod)来实现,只需要将方法声明为静态方法即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值