Как стать автором
Обновить

Комментарии 13

Зачем приводить пример, который нарушает SOLID? (Пример с if else).

Поскольку код в статье писался для примера, не учитывая принципы SOLID.

А могли бы вы рассказать как пример с if-else нарушает SOLID и какой именно принцип?

Open-Closed, можете почитать в интернете.

А как правильно?

Есть сайт с названием RefactoringGuru. Там примеры есть для питона и других языков к разным паттернам. По нему учил паттерны.

Пример неудачного "примера". Глобальные переменные, статики, смешивание ответственности (определение класса создаваемого объекта и собственно создание объекта). И сами примеры не вычитывались, в частности

if isinstance(class_name, Hashable):
raise ValueError("class_name must be a Hashable type!")

Тут явно пропущен NOT например

Да, вы правы, проглядел, поправил. Также изменил возвращаемый результат методов - с инстансов на сами классы.

А толку от фабрики, которая возвращает экземпляры классов не реализующие единый интерфейс? Имхо, фабрики приведённые в статье больше похожи на ServiceLocator'ы.

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

Ну так выкинули бы мусор, как раз хватило бы места статьи показать единый интерфейс. Ваш же пример в читаемом для демонстрации именно паттерна, а не типизации и обработки ошибок.

class Factory(object):
    def get(class_name):
        classes = {
            "SubjectOne": SubjectOne,
            "SubjectTwo": SubjectTwo
        }
        return classes[class_name]()

Ключи словаря вообще всегда Hachable. Что вы пытались показать поставив везде str и только в этом примере Hachable?

А для чего нужно явное наследование от object? Пора бы уже от обратной совместимости с небезопасными версиями отказываться в новом коде хотя бы.

А как вам такой вариант? https://www.geeksforgeeks.org/bridge-method-python-design-patterns/

class Cuboid:
 
    class ProducingAPI1:
 
        """Implementation Specific Implementation"""
 
        def produceCuboid(self, length, breadth, height):
 
            print(f'API1 is producing Cuboid with length = {length}, '
                  f' Breadth = {breadth} and Height = {height}')
 
    class ProducingAPI2:
        """Implementation Specific Implementation"""
 
        def produceCuboid(self, length, breadth, height):
            print(f'API2 is producing Cuboid with length = {length}, '
                  f' Breadth = {breadth} and Height = {height}')
 
 
    def __init__(self, length, breadth, height):
 
        """Initialize the necessary attributes"""
 
        self._length = length
        self._breadth = breadth
        self._height = height
 
    def produceWithAPI1(self):
 
        """Implementation specific Abstraction"""
 
        objectAPIone = self.ProducingAPI1()
        objectAPIone.produceCuboid(self._length, self._breadth, self._height)
 
    def producewithAPI2(self):
 
        """Implementation specific Abstraction"""
 
        objectAPItwo = self.ProducingAPI2()
        objectAPItwo.produceCuboid(self._length, self._breadth, self._height)
 
    def expand(self, times):
 
        """Implementation independent Abstraction"""
 
        self._length = self._length * times
        self._breadth = self._breadth * times
        self._height = self._height * times
 
# Instantiate a Cuboid
cuboid1 = Cuboid(1, 2, 3)
 
# Draw it using APIone
cuboid1.produceWithAPI1()
 
# Instantiate another Cuboid
cuboid2 = Cuboid(19, 20, 21)
 
# Draw it using APItwo
cuboid2.producewithAPI2()

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории