Паттерны Фабричный метод и Абстрактная фабрика - порождающие
Фабричный метод определяет интерфейс для создания объекта, но оставляет производным классам решение, какой именно класс инстациировать
Простыми словами, фабричный метод - абстрактная команда, которая может иметь разную реализацию у разных наследников.
Tip
Допустим, существуют норвежский и японский кузнец, каждый из которых делает мечи.
Понятное дело, что норвежский и японский кузнец наследуют от абстрактного класса (интерфейса) кузнец,
а норвежский меч и катана наследуют от абстрактного класса (интерфейса) меч.
В результате кузнец и будет у нас фабрикой по прозводству мечей (продуктов).
Абстрактная же фабрика представляет собой кузнеца, который производит снаряжение - например, шлем, броню и меч (то есть, семейство продуктов).
Таким образом:
- Логика создания объектов в отдельном модуле. => Избегается дублирование кода и комфортнее поддержка и модификация.
- метод и возвращаемый объект являются абстрактными. => Код становится более гибким, логики проще переключить.
from abc import ABC, abstractmethod
class Sword(ABC):
def __init__(self, sharpness, length, handle, creator):
self._sharpness = sharpness
self._length = length
self._handle = handle
self._creator = creator
@abstractmethod
def __str__(self, sword_name):
return "{}. Сделал: {}; Острота: {}; Длина: {}; Рукоять: {}" \
.format(sword_name, self._creator, self._sharpness, self._length, self._handle)
class NorwegianSword(Sword):
def __init__(self, sharpness, length, creator):
handle = "Широкая рукоять"
super().__init__(sharpness, length, handle, creator)
def __str__(self):
return super().__str__("Норвежский меч")
class JapaneseSword(Sword):
def __init__(self, sharpness, length, creator):
handle = "Тонкая рукоять"
super().__init__(sharpness, length, handle, creator)
def __str__(self):
return super().__str__("Катана")
class Blacksmith(ABC):
def __init__(self, name, clothes):
self._name = name
self._clothes = clothes
@abstractmethod
def __str__(self):
pass
@abstractmethod
def makeSword(self):
pass
class NorwegianBlacksmith(Blacksmith):
def __init__(self, name):
clothes = "Старая рубаха"
super().__init__(name, clothes)
def __str__(self):
return "Норвежский кузнец"
def makeSword(self):
self.sword = NorwegianSword("Немного острый", "Короткий", self.__str__())
return self.sword
class JapaneseBlacksmith(Blacksmith):
def __init__(self, name):
clothes = "Аккуратный белый халат"
super().__init__(name, clothes)
def __str__(self):
return "Японский кузнец"
def makeSword(self):
self.sword = JapaneseSword("Острый", "Длинный", self.__str__())
return self.swordTip
Теперь, допустим, какой-нибудь заказчик приходит к норвежскому и японскому кузнецу и говорит обоим сделать меч.
Important
ВАЖНО: Заказчик не выбирает, какой меч сделает тот или иной кузнец, и никак повлиять на это не может. Вместо этого заказчик просто дает задание кузнецу сделать меч и потом получает этот меч.
norw_bsm = NorwegianBlacksmith("Сигурд")
norw_sword = norw_bsm.makeSword()
print(norw_sword)
japan_bsm = JapaneseBlacksmith("Харуто")
japan_sword = japan_bsm.makeSword()
print(japan_sword)
# output:
# Норвежский меч. Сделал: Норвежский кузнец; Острота: Немного острый; Длина: Короткий; Рукоять: Широкая рукоять
# Катана. Сделал: Японский кузнец; Острота: Острый; Длина: Длинный; Рукоять: Тонкая рукоять