Ответ
Паттерн Фабрика (Factory) — это порождающий паттерн проектирования, который предоставляет интерфейс для создания объектов, но позволяет подклассам решать, объекты каких именно классов создавать. Он инкапсулирует логику инстанцирования, скрывая её от клиентского кода.
Основные цели и преимущества:
- Инкапсуляция логики создания: Клиентскому коду не нужно знать о конкретных классах и сложностях их создания. Он просто запрашивает нужный объект у фабрики.
- Снижение связанности (Decoupling): Клиентский код зависит от абстрактного интерфейса продукта и фабрики, а не от конкретных реализаций. Это упрощает замену или добавление новых типов продуктов.
- Соблюдение принципа открытости/закрытости (OCP): Можно вводить новые типы продуктов, не изменяя существующий клиентский код, который использует фабрику.
Пример (Простая Фабрика на Python):
from abc import ABC, abstractmethod
# Абстрактный продукт
class PaymentMethod(ABC):
@abstractmethod
def pay(self, amount: float):
pass
# Конкретные продукты
class CreditCard(PaymentMethod):
def pay(self, amount: float):
print(f"Оплачено {amount} кредитной картой.")
class PayPal(PaymentMethod):
def pay(self, amount: float):
print(f"Оплачено {amount} через PayPal.")
# Фабрика для создания объектов
class PaymentFactory:
@staticmethod
def get_payment_method(method: str) -> PaymentMethod:
if method == "credit_card":
return CreditCard()
elif method == "paypal":
return PayPal()
raise ValueError(f"Неизвестный метод оплаты: {method}")
# Клиентский код
payment_method = PaymentFactory.get_payment_method("paypal")
payment_method.pay(100.50)
# Вывод: Оплачено 100.5 через PayPal.
Когда применять:
- Когда заранее неизвестно, объекты каких именно классов нужно будет создавать.
- Когда система должна быть независимой от процесса создания и композиции своих продуктов.
- Когда вы хотите предоставить пользователям библиотеки только интерфейс для создания объектов, скрыв реализацию.
Ответ 18+ 🔞
Да ты посмотри, какой народ-то изобретательный, блядь! Взяли и придумали целый паттерн, чтобы просто объекты создавать, ёпта! Называется Фабрика (Factory). Это ж надо, сука, до такого додуматься!
Ну, короче, смотри. Есть у тебя какая-то хрень, которую нужно создавать. Но создавать её по-разному, в зависимости от условий. И чтобы клиентский код — этот, который пользуется твоей поделкой — не превращался в помойку из if-else на триста строк, его нужно от этой всей кухни отгородить. Вот фабрика и есть такая хитрая жопа, которая берёт на себя весь этот геморрой.
Зачем это, спрашивается, надо, нахуй?
- Спрятать сраку (инкапсуляция): Тому, кто пользуется, вообще похуй, как там внутри объект склеивается. Он просто говорит: «Эй, фабрика, дай мне вот это». А она уже сама решает, какую конкретно хуйню ему подсунуть и как её собрать.
- Развязать всё нахуй (снижение связанности): Твой основной код теперь не привязан к конкретным классам. Он общается с абстракцией — интерфейсом продукта и фабрикой. Захотел поменять реализацию — поменял её в одном месте, в фабрике, и всё, пиздец, работает.
- Не трогай старое, добавляй новое (принцип OCP): Нужен новый тип объекта? Добавил новый класс продукта и дописал пару строк в фабрику. Весь остальной код, который уже работал, можно даже не дышать, он и так сработает.
Смотри, как это выглядит в коде, на примере оплаты:
from abc import ABC, abstractmethod
# Это типа общая идея платежа. Все платёжки должны уметь платить.
class PaymentMethod(ABC):
@abstractmethod
def pay(self, amount: float):
pass
# А вот конкретные ребята, которые умеют платить по-своему.
class CreditCard(PaymentMethod):
def pay(self, amount: float):
print(f"Оплачено {amount} кредитной картой. Чик-чирик и готово!")
class PayPal(PaymentMethod):
def pay(self, amount: float):
print(f"Оплачено {amount} через PayPal. Пиу-пиу, деньги улетели!")
# А вот она, звезда вечера — наша фабрика, блядь!
# Её задача — рожать нужные объекты, не загружая мозг пользователя.
class PaymentFactory:
@staticmethod
def get_payment_method(method: str) -> PaymentMethod:
if method == "credit_card":
return CreditCard()
elif method == "paypal":
return PayPal()
# А если пришла какая-то хуйня, которую мы не знаем — сразу в сраку ошибку!
raise ValueError(f"Ёб твою мать, какой это метод оплаты: {method}?!")
# А теперь смотрим, как этим всем пользоваться. Красота же!
# Хочу платить через PayPal — и не парюсь, как его создавать.
payment_method = PaymentFactory.get_payment_method("paypal")
payment_method.pay(100.50)
# Выведет: Оплачено 100.5 через PayPal. Пиу-пиу, деньги улетели!
Так когда же эту фабрику впихивать, а?
- Когда сходу нихуя не ясно, объекты какого именно класса придётся создавать. Всё решится в рантайме.
- Когда хочется отвязать основную логику от всей этой возни с конструкторами и зависимостями при создании объектов.
- Когда пишешь библиотеку, и нужно дать пользователю удобный способ создавать сложные штуки, не показывая ему свою кухню, а то ещё обосрётся чего.