人们会渐渐爱上那些使他们丧失思考能力的工业技术.——《美丽新世界》
Pyhton中的工厂模式(factory pattern)
工厂模式是说调用方通过调用一个简单函数就可以创建不同的对象,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。一般包括:
- 简单工厂(Simple Factory)
- 工厂方法(factory method)
- 抽象工厂(abstract factory)
1.简单工厂
简单工厂(Simple Factory)模式,又称静态工厂方法模式(Static Factory Method Pattern)它属于类创建型模式。在简单工厂模式中,可以根据自变量的不同返回不同类的实例。
简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
与策略模式类似,都是通过多态来实现不同子类的选取。
def create_animal(name):
if name == 'dog':
return Dog()
elif name == 'cat':
return Cat()
animal = create_animal('dog')
animal.eat('some food')
简单工厂模式的优缺点
优点: (1)工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。
(2)客户端无需知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。
(3)通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
缺点: (1)由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
(2)使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。
(3)系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
(4)简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
2. 工厂方法
工厂方法模式 又称多态性工厂(Polymorphic Factory)模式或虚拟构造子(Virtual Constructor)模式。 虽然又叫多态性工厂,但工厂方法并不是严格意义上的多态。
是指定义一个可以根据输入参数的不同返回不同对象的函数。
class JSONParser:
def parse(self, raw_data):
return json.loads(raw_data)
class XMLParser:
def parse(self, raw_data):
return xml2dict(raw_data)
def new_parser(type, **kwargs):
if type == 'json':
return JSONParser()
elif type == 'xml':
return XMLParser()
parser = new_parser('json')
with open('hello.json') as fp:
data = parser.parse(fp.read())
print(data)
工厂方法模式的优缺点
- 优点:
(1)隐藏了何种具体产品类被实例化这一细节,用户只需要关心所需产品对应的工厂,无需关心创建细节,甚至无需知道具体产品类的类名。
(2)工厂角色和产品角色的多态性设计,让工厂自主确定创建何种产品对象,如何创建的细节封装在具体工厂内部。
(3)在系统加入新产品时,无需修改抽象工厂和抽象产品所提供的接口,无需修改客户端,也无需修改其他的具体工厂和具体产品,只要加一个具体产品以及和一个它对应的具体工厂就可以。完全符合开闭原则。
- 缺点
(1)添加新产品时,需要编写新的具体产品类,而且还要提高与之对应的具体工厂类,类的个数成对增加。增大了复杂度,带来额外开销。
(2)考虑到可扩展性,需要引入抽象层,增加系统的实现难度
3.抽象工厂
一系列的工厂方法组合在一起实现了一个抽象工厂。
工厂方法适合对象种类较少的情况,如果有多种不同类型对象需要创建,使用抽象工厂模式。以实现一个游戏的例子说明,在一个抽象工厂类里实现多个关联对象的创建:
class Frog:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
def interact_with(self, obstacle):
""" 不同类型玩家遇到的障碍不同 """
print('{} the Frog encounters {} and {}!'.format(
self, obstacle, obstacle.action()))
class Bug:
def __str__(self):
return 'a bug'
def action(self):
return 'eats it'
class FrogWorld:
def __init__(self, name):
print(self)
self.player_name = name
def __str__(self):
return '\n\n\t----Frog World -----'
def make_character(self):
return Frog(self.player_name)
def make_obstacle(self):
return Bug()
class Wizard:
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
def interact_with(self, obstacle):
print('{} the Wizard battles against {} and {}!'.format(
self, obstacle, obstacle.action()))
class Ork:
def __str__(self):
return 'an evil ork'
def action(self):
return 'kill it'
class WizardWorld:
def __init__(self, name):
print(self)
self.player_name = name
def __str__(self):
return '\n\n\t------ Wizard World -------'
def make_character(self):
return Wizard(self.player_name)
def make_obstacle(self):
return Ork()
class GameEnvironment:
""" 抽象工厂,根据不同的玩家类型创建不同的角色和障碍 (游戏环境)
这里可以根据年龄判断,成年人返回『巫师』游戏,小孩返回『青蛙过河』游戏"""
def __init__(self, factory):
self.hero = factory.make_character()
self.obstacle = factory.make_obstacle()
def play(self):
self.hero.interact_with(self.obstacle)
抽象工厂模式的优缺点
优点: (1) 隔离了具体类的生成,使得用户不需要知道什么被创建了。 (2) 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
缺点: (1)添加新的产品对像时,难以扩展抽象工厂以便生产新种类的产品。
参考链接: