Использование фабричных идиом Python - PullRequest
0 голосов
/ 23 октября 2018

Ниже приведен шаблон из: https://python -3-patterns-idioms-test.readthedocs.io / en / latest / Factory.html .Мой вопрос заключается в следующем: действительно ли это лучшая идиома / шаблон для создания универсальных объектов в Python 3.x?Я не могу найти много по этой теме.Код ниже:

class Shape(object):
    # Create based on class name:
    def factory(type):
        #return eval(type + "()")
        if type == "Circle": return Circle()
        if type == "Square": return Square()
        assert 0, "Bad shape creation: " + type
    factory = staticmethod(factory)

class Circle(Shape):
    def draw(self): print("Circle.draw")
    def erase(self): print("Circle.erase")

class Square(Shape):
    def draw(self): print("Square.draw")
    def erase(self): print("Square.erase")

# Generate shape name strings:
def shapeNameGen(n):
    types = Shape.__subclasses__()
    for i in range(n):
        yield random.choice(types).__name__

shapes = \
  [ Shape.factory(i) for i in shapeNameGen(7)]

for shape in shapes:
    shape.draw()
    shape.erase()

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

1 Ответ

0 голосов
/ 23 октября 2018

Я мог бы что-то упустить, но мне не нравится этот шаблон.

У вас уже есть фабрики для Circle и Square - Circle и Square.:)

Код в вашем вопросе излишне жестко кодирует имена классов в factory, а затем проходит через некоторые дополнительные циклы, получая имена подклассов Shape и затем вызывая factory с этими именами.

Более прямой способ создания списка shapes:

types = Shape.__subclasses__()
shapes = [random.choice(types)() for _ in range(7)]

У меня есть ситуация, когда мне могут быть заданы несколько геометрий.Это упрощенный пример, но я получаю ответ JSON с различными геометриями, и вместо того, чтобы писать несколько операторов if несколько раз, я подумал, что использование Factory может уменьшить проблему: поэтому Shape (JSON) -> Circle or Shape (JSON) - Квадрат

Это не оправдывает factory, как это здесь закодировано.Вы можете иметь простой словарь, например

classes = {'Circle': Circle, 'Square': Square, ...}

, или, возможно, создать его динамически с помощью

classes = {cls.__name__:cls for cls in Shape.__subclasses__()}

, а затем вызвать classes[some_string]() для создания экземпляра.Вы даже можете динамически создавать экземпляр класса по строковому имени , используя getattr.

...