Найти - Пользователи
Полная версия: Полиморфные классы
Начало » Центр помощи » Полиморфные классы
1
iDarkLord
В общем имеется некоторый базовый класс от которого унаследованы некоторые другие, мне нужно определить способ автоматического создания экземпляра нужного класса их этого перечня.

 class Base:
   pass
class First(Base):
    def somemethod():
    # Specific to First class somemethod implementation
    pass
class Second(Base):
    def somemethod():
    # Specific to Second class somemethod implementation
    pass

В некоторую функцию передается один ключевой параметр - он определяет фактически объект какого класса потребуется, и параметры инициализации объекта. Я читал про фабричный метод но сейчас я его представляю его как то так:

 class Base:
   def __init__(self, classid, params):
      if classid == "First":
        self.instance = First(params)
      if classif == "Second":
        self.instance = Second(params)
   def get_instance():
      return self.instance
class First(Base):
    def somemethod():
    # Specific to First class somemethod implementation
    pass
class Second(Base):
    def somemethod():
    # Specific to Second class somemethod implementation
    pass
InstanceOfRequiredClass =  Base(classid, *params).get_instance()

Насколько я понял в терминологии паттернов проектирования таким образом реализованный конструктор класса Base называется фабричным методом. Так ли это ?
Решение проблемы описанное выше мне не нравится прежде всего наличием этого жуткого говнокода в виде ифов в __init__ методе. И каждый раз добавляя новый функционал я должен буду писать в этом методе новый иф. Вторая проблема никто не запрещает инстанциировать экземпляры First и Second не через конструирование Base. Как обойти названные проблемы ?
Rodegast
> Насколько я понял в терминологии паттернов проектирования

Забудь про паттерны проектирования:
 def getInstanc(classid, params):
    if classid == "First":
        return First(params)
    else:
        return Second(params)
InstanceOfRequiredClass = getInstanc(classid, params)
iDarkLord
Rodegast
Забудь про паттерны проектирования:
Было б чего забывать.
Но проблема с ифами как была так и осталась.
Кстати почему тогда все реализации фабричного метода что я видел были сделаны как методы класса, а не как просто функция. Я так сходу не могу найти минусов такого подхода.
Rodegast
> Но проблема с ифами как была так и осталась.

Ели тебе if не нравится то можешь писать как-то так:
 globals()[classid](params)
P.S. Вот тебе пример реализации этого шаблона:
https://github.com/pkolt/design_patterns/blob/master/generating/abstract_factory.py
JOHN_16
iDarkLord
как одно из решений, которое широко применялось (по крайней мере раньше) можно регистрировать дочерние классы базовым классом. Условный пример:
 class Factory:
    _storage = {}
    @classmethod
    def register_class(cls, class_obj, slug):
        cls._storage[slug] = class_obj
    def __call__(self, slug, *args, **kwargs):
        return Factory._storage[slug](*args, **kwargs)
class Base:
    def __init__(self, name):
        self._name = name
    def __str__(self):
        return  '{} "{}"'.format(self.__class__.__name__, self._name)
class First(Base):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    def somemethod():
    # Specific to First class somemethod implementation
        pass
class Second(Base):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
    def somemethod():
    # Specific to Second class somemethod implementation
        pass
Factory.register_class(First, 'first')
Factory.register_class(Second, 'second')
factory = Factory()
print(factory(slug='second', name='2nd class'))
print(factory(slug='first', name='1st class'))
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB