建立型模式---工厂模式

工厂模式html

在工厂设计模式中,客户端能够请求一个对象,而无须要知道这个对象来自哪里,也就是使用哪一个类来生成这个对象。工厂背后的思想是简化对象的建立。与客户端本身基于类实例化直接建立对象相比,基于一个中心化函数来实现,更易于追踪建立了那些对象。
工厂一般有两种形式:一种是工厂方法,它是一个方法(函数),对不一样的输入参数返回不一样的对象;第二种是抽象工厂,它是一组用于建立一系列相关事物对象的工厂方法。

工厂方法sql

在工厂方法模式中,咱们执行单个函数,传入一个参数(提供信息代表咱们想要什么),但不要求直到任何关于对象如何实现以及对象来自哪里的细节。
现实生活中的例子:塑料玩具制造制造塑料玩具的压塑粉都是同样的,可是使用不一样塑料模具就能产出不一样的外形。好比有一个工厂方法,输入是目标外形的名称,输出则是要求的塑料外形。
软件中的例子:Django框架使用工厂方法模式来建立表单字段。Django的forms模块支持不一样种类字段(CharField,EmailField)的建立和制定(max_length,required)。
应用案例:
若是由于应用建立对象的代码分布在多个不一样的地方,而不是仅在一个函数/方法中,你发现无法跟踪这些对象,那么应该考虑使用工厂方法模式。工厂方法集中地在一个地方建立对象,使对象跟踪变得更容易。

案例实现django

如下例子将关注两种流行的人类可读文件格式:XML和JSON。
在当前这个问题中,咱们有一些输入数据存储在一个XML文件和JSON文件中,要对这两个文件进行解析,获取一些信息。同时,但愿对这些(以及未来涉及的的全部)外部服务进行集中式的客户端链接。咱们使用工厂方法来解决这个问题。
#数据来源:
json文件:http://opensource.adobe.com/Spry/samples/data_region/JSONDataSetSample.html#Example4
xml文件:https://en.wikipedia.org/wiki/JSON#XML
import xml.etree.ElementTree as etree
import json

#类JSONConnector解析JSON文件,经过parsed_data()方法以一个字典dict的形式返回数据
class JSONConnector:
    def __init__(self,filepath):
        self.data = {}
        with open(filepath,mode='r',encoding='utf-8') as f:
            self.data = json.load(f)

    @property
    def parsed_data(self):
        return self.data

#类XMLConnector解析XML文件,经过parsed_data()方法以xml.etree.Element列表的形式返回全部数据。
class XMLConnector:
    def __init__(self,filepath):
        self.tree = etree.parse(filepath)

    @property
    def parsed_data(self):
        return self.tree

#工厂方法connect_factory,基于输入路径的扩展名返回一个JSONConnector或XMLConnector的实例
def connect_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)

#函数connnect_to对工厂方法进行包装,添加了异常处理
def connect_to(filepath):
    factory = None
    try:
        factory = connect_factory(filepath)
    except ValueError as e:
        print(e)
    return factory

def main():
    sqlite_factory = connect_to('person.sq3')
    print()

    xml_factory = connect_to('test2.xml')
    xml_data = xml_factory.parsed_data
    liars = xml_data.findall(".//{}[{}='{}']".format('person','lastName','Liar'))
    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.text)) for p in liar.find('phoneNumber')]#待完善XML模式匹配语法
    print()

    json_factory = connect_to('test1.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']]

if __name__ == '__main__':
    main()

抽象工厂json

抽象工厂设计模式是抽象方法的一种泛化。归纳来讲,一个抽象工厂是(逻辑上的)一组工厂方法,其中每一个工厂方法负责产生不一样种类的对象。
现实生活中的例子:汽车制造业应用了抽象工厂的思想。冲压不一样汽车模型的部件(车门、仪表盘、车篷以及挡泥板的等)所使用的的机件是相同的。机件组装起来的模型随时可配置,且易于改变。
软件中的例子:程序包django_factory是一个用于在测试中建立Django模型的抽象工厂实现,可用来为支持测试专有属性的模型建立实例。这能让测试代码的可读性更高,且能避免共享没必要要的代码,故有其存在的价值。
应用案例:
抽象工厂模式是工厂方法模式的一种泛化,因此它能提供相同的好处:让对象的建立更容易追踪;将对象建立与使用解耦;提供优化内存占用和应用性能的潜力。
那咱们什么时候使用工厂方法,什么时候又该使用抽象工厂?答案是,一般一开始使用工厂方法,由于它更简单。若是后来发现应用须要许多工厂方法,那么会将建立一些列对象的过程合并在一块儿更合理,从而最终引入抽象工厂。
#想象一下,咱们正在创造一个游戏,或者想在应用中包含一个迷你游戏让用户娱乐一下。咱们但愿至少包含两个游戏,一个面向孩子,一个面向大人。在运行时,基于用户输入,决定该建立那个游戏并运行。游戏的建立部分由一个抽象工厂维护。
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'

#抽象工厂FrogWorld,其主要职责是建立游戏的主人公和障碍物。
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 'a evil ork'

    def action(self):
        return 'kills it'

#抽象工厂WizardWorld,相似于FrogWorld
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()

#类GameEnvironment是咱们游戏的主入口,它接受factory做为输入,用其建立游戏的世界。
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)

#validate_age提示用户输入一个有效的年龄
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()

小结设计模式

工厂方法设计模式的实现是一个不属于任何类的单一函数,负责单一种类对象的建立。
抽象工厂设计模式的实现是同属于单个类的许多个工厂方法用于建立一系列种类的相关对象。
相关文章
相关标签/搜索