简介
工厂模式与建造者模式都属于创建型模式。
在工厂模式中,客户端在不知道对象来源(即不知道该对象是用哪个类产生的)的情况下,要求创建一个对象。
工厂模式背后的思想是简化对象的创建过程。
工厂模式通常有两种形式:
- 工厂方法,它是一个方法(或以地道的 Python 术语来说,是一个函数),针对不同的输入参数返回不同的对象。
- 抽象工厂,它是一组用于创建一系列相关对象的工厂方法。
当需要构建更为复杂的对象时,可以使用建造者模式。
建造者与工程模式的区别:
工厂模式在单个步骤中创建对象,而建造者模式在多个步骤中创建对象,而且几乎总是使用指挥者。
建造者模式通常包括两个部分:
- 建造者(builder):负责创建复杂对象的各个部分的组件
- 指挥者(director):使用建造者实例控制构建过程的组件
工厂方法
工厂方法基于单一的函数来处理对象创建任务。执行工厂方法、传入一个参数以提供体现意图的信息,就可以创建想要的对象。
例如:createProduct,只需要提供产品名称就可以返回对应的 Product
- createProduct( “Product1” )
- createProduct( “衬衣” )
例如:Django 框架使用工厂方法来创建表单字段
- forms.CharField(max_length=100)
- forms.DateField(required=False)
1、什么时候使用工厂方法模式
如果你发现,创建对象的代码分布在许多不同的地方,而不是在单一的函数/方法中,导致 难以跟踪应用中创建的对象,这时就应该考虑使用工厂方法模式了。
工厂方法将对象创建过程集 中化,使得追踪对象变得更容易。
创建多个工厂方法完全没有问题,实践中也通常这么做。
2、工厂方法模式的优点
将对象的创建与使用解耦,修改工程方法十分容易,而且不需要同时修改使用这个工程方法的代码。
工厂方法仅在绝对必要时才创建新的对象,可以提升性能与内存使用率。
3、工厂方法案例1:HTML 按钮工厂
HTML 按钮有几种类型:Button, Input, Image
开发一个工厂方法,通过传入的参数返回不同的按钮的 html 代码
# 工厂方法案例1:HTML 按钮工厂
class Button(object):
html = "<button></button>"
def get_html(self):
return self.html
class Image(Button):
html = "<img></img>"
class Input(Button):
html = "<input></input>"
def create_button(name):
c_name = name.capitalize()
if c_name in ['Button', 'Image', 'Input' ]:
return globals()[c_name]()
print(create_button('image').get_html())
<img></img>
4、工厂方法案例2:将create_button 封装到一个类中
多个工厂方法可以再使用一个类进行封装
# 工厂方法案例2:将create_button 封装到一个类中
# 可以将其他 create 方法都放在 HTMLFactory 中
class HTMLFactory:
button_types = ['Button', 'Image', 'Input' ]
def create_button(self, name):
c_name = name.capitalize()
if c_name in self.button_types:
return globals()[c_name]()
print(HTMLFactory().create_button('button').get_html())
<button></button>
抽象工厂
抽象工厂设计模式是一种一般化的工厂方法。
一个抽象工厂是一些工厂方法的集合,其中每一个工厂方法负责生成一种不同的对象。
1、什么时候使用 工厂方法、抽象工厂
通常从 简单的工厂方法开始。
如果发现应用程序需要许多工厂方法,且将这些方法组合起来创建一系列 对象是有意义的,那么就使用抽象工厂。
2、抽象工厂案例1:玩具工厂
定义一个抽象工厂,内有多个工厂方法。
定义两个玩具工厂,分别生产汽车玩具,毛绒玩具。
# 抽象工厂案例1:玩具工厂
from abc import ABC, abstractmethod
class AbstractToy(ABC):
@abstractmethod
def name(self) ->str:
pass
@abstractmethod
def price(self) -> int:
pass
class AbstractFactory(ABC):
@abstractmethod
def create_toy(self, name) -> AbstractToy:
pass
class CarToyFactory(AbstractFactory):
types = ['BMW', 'Porsche', 'Buick']
def create_toy(self, name):
# 这里省略部分代码,具体实现参考工厂方法
return "Car Toy:" + name
class StuffedToyFactory(AbstractFactory):
types = ['Bear', 'Cat', 'Dog']
def create_toy(self, name):
return "Stuffed Toy:" + name
factory = CarToyFactory()
print( factory.create_toy('BMW'))
Car Toy:BMW
建造者模式
在不太适合使用工厂模式(工厂方法或抽象工厂)的情况下,我们使用建造者模式创建对象。
想要创建一个复杂的对象(一个由许多部分组成的对象,并且可能需要遵循特定的顺序 在不同的步骤中创建)。
需要对象的不同表现形式,并希望保持对象的构造与表示解耦。
希望在某个时间点创建一个对象,但在稍后的时间点访问它。
### 流畅建造者示例
class Pizza:
def __init__(self, builder):
self.garlic = builder.garlic
self.extra_cheese = builder.extra_cheese
def __str__(self):
garlic = 'yes' if self.garlic else 'no'
cheese = 'yes' if self.extra_cheese else 'no'
info = (f'Garlic: {garlic}', f'Extra cheese: {cheese}')
return '\n'.join(info)
# 建造者模式
class PizzaBuilder:
def __init__(self):
self.extra_cheese = False
self.garlic = False
def add_garlic(self):
self.garlic = True
return self
def add_extra_cheese(self):
self.extra_cheese = True
return self
def build(self):
return Pizza(self)
if __name__ == '__main__':
pizza = Pizza.PizzaBuilder().add_garlic().add_extra_cheese().build()
print(pizza)
```
Garlic: yes
Extra cheese: yes
总结
工厂模式有两种形式:工厂方法与抽象工厂,优先使用工厂方法实现
工厂模式的优点:
将对象的创建与使用解耦,修改工程方法十分容易,而且不需要同时修改使用这个工程方法的代码;
工厂方法仅在绝对必要时才创建新的对象,可以提升性能与内存使用率。
文源网络,仅供学习之用,如有侵权,联系删除。
我将优质的技术文章和经验总结都汇集在了我的公众号【Python圈子】里,为方便大家学习,还整理了一套学习资料,免费提供给热爱Python的同学! 更有学习交流群,多交流问题才能更快进步~