Pyhotn工厂模式

来源:互联网 发布:淘宝网排名怎么靠前 编辑:程序博客网 时间:2024/06/04 01:02

工厂模式形式

  • 工厂方法:对不同的输入参数返回不同对象;
  • 抽象工厂:是一组用于创建一系列相关事物对象的工厂方法。

工厂方法

数据来源形式:

  • 人们可读文件:XML、Atom、YAML、JSON等
  • 二进制文件:.sq3、.mp3

问题:

  • 有一些数据存储在XML和JSON文件中,对这两个文件进行解析,获取一些信息;
  • 对这些外部服务进行集中式的客户端连接。

数据形式:

  • JSON
[    {        "id": "0001",        "type": "donut",        "name": "Cake",        "ppu": 0.55,        "batters": {            "batter": [                {                    "id": "1001",                    "type": "Regular"                },                {                    "id": "1002",                    "type": "Chocolate"                },                {                    "id": "1003",                    "type": "Blueberry"                },                {                    "id": "1004",                    "type": "Devil's Food"                }            ]        },        "topping": [            {                "id": "5001",                "type": "None"            },            {                "id": "5002",                "type": "Glazed"            },            {                "id": "5005",                "type": "Sugar"            },            {                "id": "5007",                "type": "Powdered Sugar"            },            {                "id": "5006",                "type": "Chocolate with Sprinkles"            },            {                "id": "5003",                "type": "Chocolate"            },            {                "id": "5004",                "type": "Maple"            }        ]    },    {        "id": "0002",        "type": "donut",        "name": "Raised",        "ppu": 0.55,        "batters": {            "batter": [                {                    "id": "1001",                    "type": "Regular"                }            ]        },        "topping": [            {                "id": "5001",                "type": "None"            },            {                "id": "5002",                "type": "Glazed"            },            {                "id": "5005",                "type": "Sugar"            },            {                "id": "5003",                "type": "Chocolate"            },            {                "id": "5004",                "type": "Maple"            }        ]    },    {        "id": "0003",        "type": "donut",        "name": "Old Fashioned",        "ppu": 0.55,        "batters": {            "batter": [                {                    "id": "1001",                    "type": "Regular"                },                {                    "id": "1002",                    "type": "Chocolate"                }            ]        },        "topping": [            {                "id": "5001",                "type": "None"            },            {                "id": "5002",                "type": "Glazed"            },            {                "id": "5003",                "type": "Chocolate"            },            {                "id": "5004",                "type": "Maple"            }        ]    }]
  • XML
<persons>     <person>       <firstName>John</firstName>       <lastName>Smith</lastName>       <age>25</age>       <address>         <streetAddress>21 2nd Street</streetAddress>         <city>New York</city>         <state>NY</state>         <postalCode>10021</postalCode>       </address>       <phoneNumbers>         <phoneNumber type="home">212 555-1234</phoneNumber>         <phoneNumber type="fax">646 555-4567</phoneNumber>       </phoneNumbers>       <gender>         <type>male</type>       </gender>     </person>     <person>       <firstName>Jimy</firstName>       <lastName>Liar</lastName>    <age>19</age>    <address>      <streetAddress>18 2nd Street</streetAddress>      <city>New York</city>      <state>NY</state>      <postalCode>10021</postalCode>    </address>    <phoneNumbers>      <phoneNumber type="home">212 555-1234</phoneNumber>    </phoneNumbers>    <gender>      <type>male</type>    </gender>  </person>  <person>    <firstName>Patty</firstName>    <lastName>Liar</lastName>    <age>20</age>    <address>      <streetAddress>18 2nd Street</streetAddress>      <city>New York</city>      <state>NY</state>      <postalCode>10021</postalCode>    </address>    <phoneNumbers>      <phoneNumber type="home">212 555-1234</phoneNumber>      <phoneNumber type="mobile">001 452-8819</phoneNumber>    </phoneNumbers>    <gender>      <type>female</type>    </gender>  </person></persons>

实现

import xml.etree.ElementTree as etree#导入python自带库,用来处理XMLimport json#处理JSONclass JSONConnector:#类JSONConnector解析JSON文件    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.dataclass XMLConnector:#类XMLConnector解析XML文件    def __init__(self, filepath):        self.tree = etree.parse(filepath)    @property    def parsed_data(self):        return self.treedef connection_factory(filepath):#工厂方法,基于输入文件路径的扩展名返回一个JSONConnector或XMLConnector的实例    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 factorydef main():    sqlite_factory = connect_to('/home/spark/下载/mpdp-code-master/chapter1/data/person.sq3')#确认异常处理是否有效,应返回“Cannot connect to /home/spark/下载/mpdp-code-master/chapter1/data/person.sq3”    print()    xml_factory = connect_to('/home/spark/下载/mpdp-code-master/chapter1/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('/home/spark/下载/mpdp-code-master/chapter1/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']]if __name__ == '__main__':    main()

输出

Cannot connect to /home/spark/下载/mpdp-code-master/chapter1/data/person.sq3found: 2 personsfirst name: Jimylast name: Liarphone number (home) 212 555-1234first name: Pattylast name: Liarphone number (home) 212 555-1234phone number (mobile) 001 452-8819found: 3 donutsname: Cakeprice: $0.55topping: 5001 Nonetopping: 5002 Glazedtopping: 5005 Sugartopping: 5007 Powdered Sugartopping: 5006 Chocolate with Sprinklestopping: 5003 Chocolatetopping: 5004 Maplename: Raisedprice: $0.55topping: 5001 Nonetopping: 5002 Glazedtopping: 5005 Sugartopping: 5003 Chocolatetopping: 5004 Maplename: Old Fashionedprice: $0.55topping: 5001 Nonetopping: 5002 Glazedtopping: 5003 Chocolatetopping: 5004 Maple

抽象工厂

问题

  • 创造一个游戏。至少包含两个游戏,一个面向孩子,一个面向成人;
  • 在运行时,基于用户输入,决定该创建哪个游戏并运行。

实现

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()

输出

Hello. What's your name? duWelcome du. How old are you? 10    ------ Frog World ———du the Frog encounters a bug and eats it!----------Hello. What's your name? duWelcome du. How old are you? 20    ------ Wizard World ———du the Wizard battles against an evil ork and kills it!

总结

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

  • 想要追踪对象的创建时;
  • 想要将对象的创建与应用解耦时;
  • 想要优化应用的性能和资源占用时。

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

原创粉丝点击