工厂方法
工厂方法集中地在一个地方创建对象,使对象跟踪变得更容易, 一个工厂方法负责连接到不同的数据库(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()
抽象工厂
抽象工厂模式是工厂方法模式的一种泛化,所以它能提供相同的好处:让对象的创建更
容易追踪;将对象创建与使用解耦;提供优化内存占用和应用性能的潜力
时该使用工厂方法,何时又该使用抽象工厂
通常一开始时使用工厂方法,因为它更简单。如果后来发现应用需要许多工厂方法,那么将创建 一系列对象的过程合并在一起更合理,从而最终引入抽象工厂
这个列子介绍了两种不同的游戏:
- 未成年 游戏命名为FrogWorld,主人公是一只青蛙,喜欢吃虫子。
- 成年人 游戏命名W为izardWorld,男巫战怪兽(如兽人)而不是吃虫子
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()