python中的工厂模式

初窥设计模式

Posted by UlyC on May 25, 2018

人们会渐渐爱上那些使他们丧失思考能力的工业技术.——《美丽新世界》

我的博客

Pyhton中的工厂模式(factory pattern)

工厂模式是说调用方通过调用一个简单函数就可以创建不同的对象,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。一般包括:

  1. 简单工厂(Simple Factory)
  2. 工厂方法(factory method)
  3. 抽象工厂(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. 优点:

(1)隐藏了何种具体产品类被实例化这一细节,用户只需要关心所需产品对应的工厂,无需关心创建细节,甚至无需知道具体产品类的类名。

(2)工厂角色和产品角色的多态性设计,让工厂自主确定创建何种产品对象,如何创建的细节封装在具体工厂内部。

(3)在系统加入新产品时,无需修改抽象工厂和抽象产品所提供的接口,无需修改客户端,也无需修改其他的具体工厂和具体产品,只要加一个具体产品以及和一个它对应的具体工厂就可以。完全符合开闭原则。

  1. 缺点

(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)添加新的产品对像时,难以扩展抽象工厂以便生产新种类的产品。

参考链接:

  1. 设计模式-工厂模式
  2. Python 设计模式: 工厂模式(factory pattern)
  3. 用 Python 实现设计模式
  4. java中的工厂模式
  5. Python设计模式 - 简单工厂模式

知识共享许可协议
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。