我们有时需要根据不同的条件来创建不同的对象,首先会想到用if --elif语句来搞定。但是会有一个弊端,就是对以后扩展非常不方面,往往需要增加elif 语句。比如下面的例子
创建个模块,模块里先设计个类的蓝图,然后让后面的类继承,并实现action具体方法。
from abc import abstractmethod,ABC
class Player(ABC):
def __init__(self,name,role):
self.name=name
self.role=role
def __str__(self):
return f'name={self.name},role={self.role}'
@abstractmethod
def action(self):
"球员的行为"
class Forward(Player):
def action(self):
print('前锋,凌空飞射')
class Mid(Player):
def action(self):
print('中位,强壮身体护卫')
class Back(Player):
def action(self):
print("后位,严防死守")
在另外一个文件里调用该模块
from player import Player,Forward,Mid,Back
from v2 import register,create
def main():
data={
'players':[
{'name':"zhang bao shui",'role':"FW"},
{'name':"zhang xuanxuan",'role':"MD"},
{'name':"zhang tianchen",'role':"BW"},
]
}
players=[]
for player in data['players']:
role=player['role']
if role=='FW':
players.append(Forward(**player))
elif role=='MD':
players.append(Mid(**player))
elif role=='Bw':
players.append(Back(**player))
for args in data['players']:
# print(args)
player=create(args)
print(player)
player.action()
main()
假如现在又增加了一个类,就要再写elif 语句做判断。又没别的方法呢?答案是有的。也是建立以各模块,模块里放一个字典,再写三个函数,分别为注册,取消注册,创建对象函数。当我们使用时就用这三个函数来完成。代码如下:
from player import Player
player_creation_functions={}
def register(role:str,creation_function)->None:
player_creation_functions[role]=creation_function
def unregister(role:str)->None:
player_creation_functions.pop(role,None)
def create(args:dict)->Player:
the_args=args.copy()
role=the_args['role']
try:
create_function=player_creation_functions[role]
return create_function(**the_args)
except KeyError:
raise ValueError(f'未知角色{role}') from None
现在将之前代码更改为:
from player import Player,Forward,Mid,Back
from v2 import register,create
def main():
data={
'players':[
{'name':"zhang bao shui",'role':"FW"},
{'name':"zhang xuanxuan",'role':"MD"},
{'name':"zhang tianchen",'role':"BW"},
]
}
players=[]
# for player in data['players']:
# role=player['role']
# if role=='FW':
# print(player)
# # print(**player)
# players.append(Forward(**player))
# elif role=='MD':
# players.append(Mid(**player))
# elif role=='Bw':
# players.append(Back(**player))
#注册
register("FW",Forward)
register("MD",Mid)
register("BW",Back)
#创建
for args in data['players']:
# print(args)
player=create(args)
print(player)
player.action()
main()
效果和之前是一样的。实际操作可以把data保存为json文件,以后只需改json文件内容即可