说明

工厂模式是一个在软件开发中用来创建对象的设计模式。

工厂模式包涵一个超类。这个超类提供一个抽象化的接口来创建一个特定类型的对象,而不是决定哪个对象可以被创建。

为了实现此方法,需要创建一个工厂类创建并返回。

当程序运行输入一个“类型”的时候,需要创建于此相应的对象。这就用到了工厂模式。在如此情形中,实现代码基于工厂模式,可以达到可扩展,可维护的代码。当增加一个新的类型,不在需要修改已存在的类,只增加能够产生新类型的子类。

工厂方法

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

example:解析xml及json文件

class JSONConnector:
    def __init__(self, filepath):
    self.data = dict()
        with open(filepath, mode = 'r', encoding = 'utf-8') as f:
            self.data = json.load(f)
    @property
    def parsed_data(self):
        return self.data

class XMLConnector:
    def __init__(self, filepath):
    self.tree = etree.parse(filepath)
    @property
    def parsed_data(self):
        return self.tree

def connection_factory(filepath):
    if filepath.endswith('json'):
    connector = JSONConnector
    elif filepath.endswith('xml'):
        connector = XMLConnector
    else :
        raise ValueError('Cannot connect to {}'.format(filepath))
    return connector(filepath)
def connect_to(filepath):
    factory = None
    try:
        factory = connection_factory(filepath)
    except ValueError as ve:
        print(ve)
    return factory
def main():
    sqlite_factory = connect_to('data/person.sq3')
    print()
    xml_factory = connect_to('data/person.xml')
    xml_data = xml_factory.parsed_data
    liars = xml_data.findall(".//{}[{}='{}']".format('person',
        'lastName', 'Liar'))
    print('found: {} persons'.format(len(liars)))
    for liar in liars:
        print('first name: {}'.format(liar.find('firstName').text))
    print('last name: {}'.format(liar.find('lastName').text))
    [print('phone number ({})'.format(p.attrib['type']),p.text) for p in liar.find('phoneNumbers')]
    print()
    json_factory = connect_to('data/donut.json')
    json_data = json_factory.parsed_data
    print('found: {} donuts'.format(len(json_data)))
    for donut in json_data:
        print('name: {}'.format(donut['name']))
        print('price: ${}'.format(donut['ppu']))
        [print('topping: {} {}'.format(t['id'], t['type'])) for t in donut['topping']]

抽象工厂

抽象工厂设计模式是抽象方法的一种泛化。概括来说,一个抽象工厂是(逻辑上的)一组工
厂方法,其中的每个工厂方法负责产生不同种类的对象

example:

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 'kills 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)


def validate_age(name):
    try:
        age = input('Welcome {}. How old are you? '.format(name))
        age = int(age)
    except ValueError as err:
        print("Age {} is invalid, please try \
        again…".format(age))
        return (False, age)
    return (True, age)


def main():
    name = input("Hello. What's your name? ")
    valid_input = False
    while not valid_input:
        valid_input, age = validate_age(name)
    game = FrogWorld if age < 18 else WizardWorld
    environment = GameEnvironment(game(name))
    environment.play()

if __name__ == '__main__':
    main()

应用场景

两种模式都可以用于以下几种
场景:

(a)想要追踪对象的创建时

(b)想要将对象的创建与使用解耦时

(c)想要优化应用的性能和资源占用时。

工厂方法设计模式的实现是一个不属于任何类的单一函数,负责单一种类对象(一个形状、
一个连接点或者其他对象)的创建。抽象工厂设计模式的实现是同属于单个类的许多个工厂方法用于创建一系列种类的相关对
象(一辆车的部件、一个游戏的环境,或者其他对象)。

例子来源:精通Python设计模式