设计模式(python实现)--工厂模式(Factory)
动机
在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?
模式定义
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦,手段:虚函数)到子类。
要点总结
- Factory Method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱。
- Factory Method模式通过面向对象的手法,将所要创建的具体对象工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。
- Factory Method模式解决“单个对象”的需求变化。缺点在于要求创建方法/参数相同。
UML
image.png红色框中表示的是稳定的部分。
例子-文件分割:
原始的分割器只支持文件分割功能
class MainForm(object):
def __init__(self):
pass
def click_button(self):
splitter = FileSplitter()
splitter.split()
class FileSplitter(object):
def split(self):
print('FileSplitter split')
if __name__ == '__main__':
main_form = MainForm()
main_form.click_button()
但是后续需要支持二进制分割、图片分割等。
而MainForm
依赖FileSplitter
。根据依赖导致原则
, MainForm
必须依赖抽象,不能依赖具体。
使用工厂方法
# -*- coding:utf-8 -*-
class MainForm(object):
def __init__(self, factory_obj):
self.factory_obj = factory_obj
def click_button(self):
splitter = self.factory_obj.create_splitter()
splitter.split()
class SplitterBase(object):
def split(self):
pass
class FileSplitter(SplitterBase):
def split(self):
print('FileSplitter split')
class BinarySplitter(SplitterBase):
def split(self):
print('BinarySplitter split')
class SplitterFactoryBase(object):
def create_splitter(self):
pass
class FileSplitterFactory(object):
def create_splitter(self):
return FileSplitter()
class BinarySplitterFactory(object):
def create_splitter(self):
return BinarySplitter()
if __name__ == '__main__':
main_form = MainForm(FileSplitterFactory())
main_form.click_button()
这样MainForm
就不依赖具体类,当随着需求变化添加新的分割器时,只需要添加对应的实现类,和工厂类即可。
对照UML分析
对照UML, 该例子中,
SplitterFactoryBase
对应AbstractFactory
SplitterBase
对应AbstractProduct
FileSplitter
和BinarySplitter
对应ConcreteProduct
FileSplitterFactory
和 BinarySplitterFactory
对应ConcreteFactory
问题
-
问题1:虽然
MainForm
不依赖具体类,但是调用MainForm
的地方,肯定需要创建具体类,不就仍然依赖了具体类了吗?
答:我们无法消除依赖,只能把依赖赶到其他地方。因此必须清楚哪里需要稳定,这里MainForm
稳定后,无论需求如何变化,不需要再修改MainForm
类,而只需要修改调用它的地方,比如这里的main()
。因此把依赖都放在一起,这样改变的时候只需要修改这里即可,从而提高代码的稳定性。 -
问题2:为什么不直接传入具体的分割器,反而如此麻烦的要创建这么多的工厂类,如下:
class MainForm(object):
def __init__(self, splitter):
self.splitter = splitter
def click_button(self):
self.splitter.split()
class SplitterBase(object):
def split(self):
pass
class FileSplitter(SplitterBase):
def split(self):
print('FileSplitter split')
class BinarySplitter(SplitterBase):
def split(self):
print('BinarySplitter split')
if __name__ == '__main__':
main_form = MainForm(FileSplitter())
main_form.click_button()
例子-造车
使用工厂模式实现造不同类型的汽车
# -*- coding:utf-8 -*-
class CarBase(object):
def speed_up(self):
pass
# 奔驰汽车
class BenzCar(CarBase):
def speed_up(self):
print('BenzCar speed_up')
# 宝马汽车
class BmwCar(CarBase):
def speed_up(self):
print('BenzCar speed_up')
class CarFactoryBase(object):
def create_car(self):
pass
class BenzFactory(CarFactoryBase):
def create_car(self):
return BenzCar()
class BmwFactory(CarFactoryBase):
def create_car(self):
return BmwCar()
if __name__ == '__main__':
car = BenzFactory().create_car()
car.speed_up()