Уведомления

Группа в Telegram: @pythonsu

#1 Окт. 7, 2016 14:43:29

iDarkLord
Зарегистрирован: 2014-02-14
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Полиморфные классы

В общем имеется некоторый базовый класс от которого унаследованы некоторые другие, мне нужно определить способ автоматического создания экземпляра нужного класса их этого перечня.

 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. Как обойти названные проблемы ?

Офлайн

#2 Окт. 7, 2016 14:55:15

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2760
Репутация: +  185  -
Профиль   Отправить e-mail  

Полиморфные классы

> Насколько я понял в терминологии паттернов проектирования

Забудь про паттерны проектирования:

 def getInstanc(classid, params):
    if classid == "First":
        return First(params)
    else:
        return Second(params)
InstanceOfRequiredClass = getInstanc(classid, params)



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#3 Окт. 7, 2016 15:13:17

iDarkLord
Зарегистрирован: 2014-02-14
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

Полиморфные классы

Rodegast
Забудь про паттерны проектирования:
Было б чего забывать.
Но проблема с ифами как была так и осталась.
Кстати почему тогда все реализации фабричного метода что я видел были сделаны как методы класса, а не как просто функция. Я так сходу не могу найти минусов такого подхода.

Отредактировано iDarkLord (Окт. 7, 2016 15:14:57)

Офлайн

#4 Окт. 7, 2016 15:39:50

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2760
Репутация: +  185  -
Профиль   Отправить e-mail  

Полиморфные классы

> Но проблема с ифами как была так и осталась.

Ели тебе if не нравится то можешь писать как-то так:

 globals()[classid](params)
P.S. Вот тебе пример реализации этого шаблона:
https://github.com/pkolt/design_patterns/blob/master/generating/abstract_factory.py



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Отредактировано Rodegast (Окт. 7, 2016 15:56:32)

Офлайн

#5 Окт. 7, 2016 17:54:43

JOHN_16
От: Россия, Петропавловск-Камчатск
Зарегистрирован: 2010-03-22
Сообщения: 3292
Репутация: +  221  -
Профиль   Отправить e-mail  

Полиморфные классы

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'))



_________________________________________________________________________________
полезный блог о python john16blog.blogspot.com

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version