Я бы сделал это с декоратором. Кроме того, хранение карты сущности -> подкласса в словаре позволяет заменить линейное сканирование поиском в режиме dict.
class EntityBase(object):
_entity_ = None
_entities_ = {}
@classmethod
def factory(cls, entity):
try:
return cls._entities_[entity]
except KeyError:
raise FactoryError(tag, "Unknown entity")
@classmethod
def register(cls, entity):
def decorator(subclass):
cls._entities_[entity] = subclass
subclass._entity_ = entity
return subclass
return decorator
factory = EntityBase.factory
register = EntityBase.register
@register('Smith')
class Smith(EntityBase):
def __init__(self, a, b):
self.a = a
self.b = b
s = factory('Smith')(1, 2)
Я не уверен, что атрибут __entity__
действительно полезен для вас, если вы просто использовали его для реализации линейного сканирования. Я оставил это, но если вы убрали его, то классам, связанным с сущностью, даже не нужно было бы наследовать от EntityBase
, и вы могли бы переименовать его во что-то вроде Registry
. Это сокращает ваше дерево наследования и открывает возможность использования классов, которые не связаны общим происхождением.
В зависимости от вашего варианта использования, лучший способ сделать это может быть просто
factory = {}
class Smith(object):
def __init__(self, a, b):
self.a = a
self.b = b
factory['Smith'] = Smith
class Jones(object):
def __init__(self, c, d):
self.c = c
self.d = d
factory['Jones'] = Jones
s = factory['Smith'](1, 2)
j = factory['Jones'](3, 4)
Декоратор более изящен и позволяет нам чувствовать себя хорошо и модно, но словарь прост, полезен и по существу. Это легко понять и сложно ошибиться. Если вам действительно не нужно сделать что-то волшебное, тогда я думаю, что это путь. В любом случае, почему вы хотите это сделать?