Комментарии 13
Зачем приводить пример, который нарушает SOLID? (Пример с if else).
Поскольку код в статье писался для примера, не учитывая принципы SOLID.
А могли бы вы рассказать как пример с if-else нарушает SOLID и какой именно принцип?
Пример неудачного "примера". Глобальные переменные, статики, смешивание ответственности (определение класса создаваемого объекта и собственно создание объекта). И сами примеры не вычитывались, в частности
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()
Подходы к реализации паттерна Фабрика в Python