工厂方法

2019-04-24  本文已影响0人  虾三

工厂方法

工厂方法集中地在一个地方创建对象,使对象跟踪变得更容易, 一个工厂方法负责连接到不同的数据库(MySQL、SQLite),

下面例子根据xml、json文件类型返回对应实例类型

import xml.etree.ElementTree as etree
import json

# 类JSONConnector解析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):
        # parsed_data()方法以一个字典(dict)
        return self.data

# XMLConnector解析 XML 文件
class XMLConnector:
    def __init__(self, filepath):
        self.tree = etree.parse(filepath)

    @property
    def parsed_data(self):
        # parsed_data()方法以xml.etree.Element列表
        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():
    json_factory = connect_to('data/person.json')
    xml_factory = connect_to('data/person.xml')
    xml_data = xml_factory.parsed_data


if __name__ == '__main__':
    main()

抽象工厂

抽象工厂模式是工厂方法模式的一种泛化,所以它能提供相同的好处:让对象的创建更
容易追踪;将对象创建与使用解耦;提供优化内存占用和应用性能的潜力

时该使用工厂方法,何时又该使用抽象工厂

通常一开始时使用工厂方法,因为它更简单。如果后来发现应用需要许多工厂方法,那么将创建 一系列对象的过程合并在一起更合理,从而最终引入抽象工厂

这个列子介绍了两种不同的游戏:

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:
    """青蛙游戏boss"""
    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()

    def interact_with(self, obstacle):
        print('{} the Wizard battles against {} and {}!'.format(self, obstacle, obstacle.action()))


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:
    """男巫游戏boss"""
    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()

上一篇 下一篇

猜你喜欢

热点阅读