Какова основная цель и результат применения паттерна ‘Фабричный метод’?

Ответ

Паттерн 'Фабричный метод' (Factory Method) — это порождающий паттерн проектирования, который определяет общий интерфейс для создания объектов, но позволяет подклассам изменять тип создаваемых объектов.

Основная цель — делегировать создание объектов от клиентского кода к дочерним классам. Это позволяет вводить новые типы продуктов, не изменяя код, который эти продукты использует.

Ключевые преимущества:

  • Инкапсуляция: Логика создания объектов скрыта от клиента.
  • Гибкость: Легко добавлять новые типы создаваемых объектов (продуктов), просто создав новый класс-создатель.
  • Слабая связанность: Клиентский код работает с абстрактным интерфейсом продукта, а не с его конкретной реализацией.

Пример на Python:

from abc import ABC, abstractmethod

# Интерфейс Продукта
class Transport(ABC):
    @abstractmethod
    def deliver(self) -> str:
        pass

# Конкретные Продукты
class Truck(Transport):
    def deliver(self) -> str:
        return "Доставка грузовиком по земле"

class Ship(Transport):
    def deliver(self) -> str:
        return "Доставка кораблем по морю"

# Абстрактный Создатель (Фабрика)
class Logistics(ABC):
    @abstractmethod
    def create_transport(self) -> Transport:
        # Это и есть Фабричный метод
        pass

    def plan_delivery(self) -> str:
        transport = self.create_transport()
        return f"Логистика: {transport.deliver()}"

# Конкретные Создатели
class RoadLogistics(Logistics):
    def create_transport(self) -> Transport:
        return Truck()

class SeaLogistics(Logistics):
    def create_transport(self) -> Transport:
        return Ship()

# Клиентский код
road_logistics = RoadLogistics()
print(road_logistics.plan_delivery()) # Вывод: Логистика: Доставка грузовиком по земле

sea_logistics = SeaLogistics()
print(sea_logistics.plan_delivery()) # Вывод: Логистика: Доставка кораблем по морю

Ответ 18+ 🔞

Давай разберём этот ваш паттерн «Фабричный метод», а то смотрю — народ путается, как мухи в паутине. Ну, типа, представь себе, что ты — главный по логистике, царь и бог, который решает, какую хуйню куда везти.

Вот сидишь ты такой и думаешь: «Бля, надо груз отправить. Но ёпта, если по земле — то грузовик, а если по морю — то корабль, а если по воздуху — то самолёт, а это уже другая история, в рот меня чих-пых!». И каждый раз в коде писать if transport_type == "truck": ... elif transport_type == "ship": ... — это же пиздец какой-то, правда? Код превращается в лапшу, в которой через месяц сам чёрт ногу сломит.

Вот тут-то и выручает Фабричный метод. Суть его, блядь, проще пареной репы, хоть и звучит умно.

Чё он делает? Он говорит: «Слушай, дружок-пирожок. Не парься, какой именно объект создавать. Просто скажи, что тебе нужен некий «Транспорт», а уж я сам разберусь, грузовик это будет или пароход».

Как это работает, ёпта?

  1. Продукт (Transport): Сначала ты объявляешь общий интерфейс для всей своей ездящей-плавающей братвы. Грузовик, корабль, велосипед — всем им надо уметь доставлять херню. У всех будет метод deliver().
  2. Конкретные продукты (Truck, Ship): Это уже реальные тачки. Грузовик доставляет по земле, корабль — по воде. Каждый из них реализует этот самый deliver() по-своему.
  3. Создатель (Logistics): А это — мозг операции. Абстрактный такой чувак, который знает алгоритм работы (спланировать доставку — plan_delivery()), но не знает конкретики. У него есть один абстрактный метод — create_transport(). Это и есть тот самый фабричный метод, ёбана!
  4. Конкретные создатели (RoadLogistics, SeaLogistics): А вот ихние сыновья уже решают. Один говорит: «А я создаю только грузовики!». Другой: «А я — только корабли!». Они реализуют этот фабричный метод и возвращают нужный объект.

И что в итоге? А в итоге клиентский код (то есть ты) работает не с кучей if-ов, а с абстракцией. Хочешь доставку по дороге? Берёшь RoadLogistics и вызываешь plan_delivery(). Он внутри сам, хитрая жопа, вызовет свой фабричный метод, создаст грузовик и всё организует. Захотел морем — взял SeaLogistics. Добавить новый вид транспорта? Да хуй с ним! Создал новый класс продукта (например, Drone) и новый класс создателя (типа AirLogistics), который этот дрон и возвращает. Основной код логики доставки (plan_delivery) менять не надо вообще, ни хуя!

Преимущества, блядь:

  • Чистота: Клиент не засран проверками типов.
  • Гибкость: Новый транспорт добавляется проще, чем я это объясняю. Создал два новых класса — и вперёд.
  • Слабая связность: Клиент привязан к интерфейсу Transport, а не к конкретным классам грузовиков и кораблей. Это охуенно.

Вот тебе живой пример на Python, смотри:

from abc import ABC, abstractmethod

# 1. Интерфейс Продукта - что должен уметь любой транспорт?
class Transport(ABC):
    @abstractmethod
    def deliver(self) -> str:
        pass

# 2. Конкретные Продукты - реальные тачки
class Truck(Transport):
    def deliver(self) -> str:
        return "Доставка грузовиком по земле"

class Ship(Transport):
    def deliver(self) -> str:
        return "Доставка кораблем по морю"

# 3. Абстрактный Создатель (Фабрика) - знает процесс, но не детали
class Logistics(ABC):
    @abstractmethod
    def create_transport(self) -> Transport:  # <--- Вот он, ёбаный фабричный метод!
        pass

    def plan_delivery(self) -> str:  # А это общий алгоритм, который не меняется
        transport = self.create_transport()  # Создаём транспорт (какой? хз!)
        return f"Логистика: {transport.deliver()}"  # Работаем с ним

# 4. Конкретные Создатели - они-то и знают, какую конкретно хуйню создавать
class RoadLogistics(Logistics):
    def create_transport(self) -> Transport:
        return Truck()  # "Я создаю только грузовики, нахуй!"

class SeaLogistics(Logistics):
    def create_transport(self) -> Transport:
        return Ship()   # "А я — только корабли, в рот меня чих-пых!"

# 5. Клиентский код - использует абстракции и не парится
road_logistics = RoadLogistics()
print(road_logistics.plan_delivery()) # Вывод: Логистика: Доставка грузовиком по земле

sea_logistics = SeaLogistics()
print(sea_logistics.plan_delivery()) # Вывод: Логистика: Доставка кораблем по морю

Короче, паттерн — огонь. Позволяет отвязать создание объектов от их использования. Как будто у тебя есть универсальный пульт (создатель), а ты просто меняешь в нём батарейки (конкретные классы), чтобы он управлял то телевизором, то кондиционером. Красота, ёпта!