zoukankan      html  css  js  c++  java
  • 设计模式一:工厂模式

    工厂模式

    源码下载地址:https://github.com/myt2000/design_patterns/tree/master/chapter1

    其实一直搞不明白的重要性,最近看了一下,确实在一定程度可以提高代码复用性,下面介绍工厂模式。

    在工厂模式设计中,客户端(调用方)可以请求一个对象,而无需知道这个对象来自哪里;也就是,使用哪个类来生成这个对象。工厂背后的思想是简化对象的创建。与客户端(调用方)自己基于类实例化直接创建对象相比,基于一个中心化函数来实现,更易于追踪创建了哪些对象。通过将创建对象的代码和使用对象的代码解耦,工厂能降低应用维护的复杂度。

    工厂通常有两种形式:

    1. 工厂方法,它是一个方法(或以地道的python术语来说,是一个函数),对不同的输入参数返回不同的结果;
    2. 抽象工厂,它是一组用于创建一系列相关事务对象的工厂方法

    1. 简单的应用案例

    class A(object):
        pass
    
    if __name__ == '__main__':
        a = A()
        b = A()
    
        print(id(a) == id(b))
        print(a, b)
    '''
    False
    <__main__.A object at 0x0000025432EF7548> <__main__.A object at 0x00000254356A11C8>
    '''
    

    可以观察出每次创建的实例的对象内存地址是不一样的

    2.工厂方法

    factory_method读取某个文件(xml或者json文件),并解析数据,其他文件格式按异常处理

    主要使用了xml.etree.ElementTree中的parse,find,findall,attrib等方法

    输出打印的时候主要用了 [print('phone number ({})'.format(p.attrib['type']), p.text) for p in liar.find('phoneNumbers')]列表表达式的方式,减少了for循环的使用

    该案例主要是针对json和xml格式的文件作为参数输入

    分别定义JSONConnector和XMLConnector对文件处理的类,文件作为参数传入后,函数connection_factory判断一下使用哪个类

    import xml.etree.ElementTree as etree
    import 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']]
    
    
    if __name__ == "__main__":
        main()
    
    

    3.抽象工厂

    根据年龄判断是否小于18岁,进入不同的实例类FrogWorldWizardWorld

    GameEnvironment初始化时根据传入的类,进入不同的类实例化,最终返回结果

    调用过程

    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 '
    
    	- - - - - - 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 '
    
    	- - - - - - Wizard World ----'
    
        def make_character(self):
            return Wizard(self.player_name)
    
        def make_obstacle(self):
            return Ork()
    
    class GameEnviroment:
    
        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 = GameEnviroment(game(name))
        environment.play()
    
    if __name__ == '__main__':
        main()
    
    

    结果:

    //大于等于18岁的结果
    Hello. What's your name? qwer
    Welcome qwer. How old are you? 56
    
    
    	- - - - - - Wizard World ----
    qwer the Wizard battles against an evil ork and kills it!
        
    //小于18岁的结果
        Hello. What's your name? henry
    Welcome henry. How old are you? 12
    
    
    	- - - - - - Frog World ----
    henry the Frog encounters a bug and eats it!
    
  • 相关阅读:
    Linux基础
    杂谈
    MySQL基础
    Effective Java-第4章
    Effective Java-第三章
    Effective Java-第二章
    mybatis
    mapper.xml文件
    Mybatis
    mybatis-config.xml文件详解
  • 原文地址:https://www.cnblogs.com/myt2000/p/11561980.html
Copyright © 2011-2022 走看看