LINUX.ORG.RU

Strategy pattern или как правильно смешать точки с котами?

 , ,


0

2

Здравствуйте. Ниже приведен искусственный (и нерабочий) пример, в котором создаются объекты разного класса в зависимости от параметра (кажется это называется паттерн стратегия). Последний класс Thingy выдает ошибку, т.к. питон не умеет, аки js, возвращать новосозданный объект из конструктора.

Подскажите, как этот пример сделать рабочим?

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def info(self):
        print('Point(', self.x, ',', self.y, ')')


class Cat:
    def __init__(self, tail_len, eyes):
        self.tail_len = tail_len
        self.eyes = eyes

    def info(self):
        print('Cat with', self.tail_len, 'metres tail and', self.eyes, 'eye(s)')


class Thingy:
    def __init__(self, what, prop1, prop2):
        if what == 'point':
            return Point(prop1, prop2)
        elif what == 'cat':
            return Cat(prop1, prop2)
        else:
            raise ValueError('Unknown thingy: ' + what)

Deleted

Pythonic way:

Thingy = {"point":Point, "cat":Cat}

thing = Thingy["cat"](500, "green")
thing = Thingy["point"](1, -1)

Паттерн «виртуальный конструктор»:

- def __init__(self, what, prop1, prop2):
+ @staticmethod
+ def create(what, prop1, prop2):

Можно ещё поизвращаться с оператором __new__, но на это моветон.

E ★★★ ()
Последнее исправление: E (всего исправлений: 1)
Ответ на: комментарий от E

Можно ещё поизвращаться с оператором __new__, но на это моветон

Точно. Забыл про __new__. Щас попробую поизвращаться

Deleted ()

Проще всего, наверное, сделать Thingy в виде декоратора над Point/Cat, т.е. хранить в нём ссылку на объект и проксировать этому объекту неизвестные методы применяемые к объекту Thingy. Если же ты хочешь чтобы при инстанциировании Thingy получались реальные Point/Cat то тебе не нужна стратегия, а нужна обычная фабрика.

no-such-file ★★★★★ ()
Ответ на: комментарий от t184256

а сооружает он фабрику.

Он же сказал что хочет стратегию. Т.е. чтобы объект вёл себя по-разному в зависимости от параметра конструктора. А не просто инстанциировать объект какого-то класса в зависимости от параметра.

no-such-file ★★★★★ ()
Ответ на: комментарий от t184256

ХЗ, что ТС хочет

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

Deleted ()
Ответ на: комментарий от Deleted

Хочу минимальными усилиями в одном месте програмы добавить вариативность: создавать разный объект в зависимости от имени

Не в том месте добавляешь. Отдельная функция или максимум staticmethod — да, конструктор — нет.

t184256 ★★★★★ ()
Ответ на: комментарий от Deleted

Фабрика не потому что имя, а потому что «разные объекты». В стратегии создаются одинаковые объекты (одного класса, или подкласса).

no-such-file ★★★★★ ()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Ок, пусть будет фабрика, я не против)

Deleted ()

Какие только причудливые формы не принимает ооп головного мозга.

Оп, def thingy(...) кря кря ну ты понел. А вообще классы по имени инстанциируются как-то так: import Cat from cat; import Point from point; instance = __dir__[classname](*props). Внезапно, да? Нюансы сам допилишь, я на питоне уже несколько лет не писал, оно может быть не в дире или еще чего не так.

anonymous ()
Ответ на: комментарий от anonymous

Умные все такие. Я же сказал, много кода уже написано и ваши суперпредложения переписать всё на функциях затронут несколько файлов и займут часа 2 скучного рефакторинга)

Deleted ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.