Ответ
Фабричный метод (Factory Method) — это порождающий паттерн проектирования, который определяет общий интерфейс для создания объектов в суперклассе, но позволяет подклассам изменять тип создаваемых объектов.
Он делегирует логику инстанцирования дочерним классам, что позволяет добавлять новые типы продуктов, не изменяя основной код.
Основные компоненты:
- Продукт (Product): Абстрактный класс или интерфейс для объектов, которые создает фабричный метод.
- Конкретный продукт (Concrete Product): Реализация интерфейса продукта.
- Создатель (Creator): Абстрактный класс, который объявляет фабричный метод, возвращающий объект продукта.
- Конкретный создатель (Concrete Creator): Класс, который переопределяет фабричный метод для создания конкретного продукта.
Пример реализации на Python
Представим систему для отправки уведомлений по разным каналам (Email, SMS).
from abc import ABC, abstractmethod
# 1. Интерфейс Продукта
class Notification(ABC):
@abstractmethod
def send(self, message: str):
pass
# 2. Конкретные Продукты
class EmailNotification(Notification):
def send(self, message: str):
print(f"Отправка Email: {message}")
class SmsNotification(Notification):
def send(self, message: str):
print(f"Отправка SMS: {message}")
# 3. Абстрактный Создатель
class NotificationCreator(ABC):
@abstractmethod
def create_notification(self) -> Notification:
"""Это и есть Фабричный метод"""
pass
def send_notification(self, message: str):
notification = self.create_notification()
notification.send(message)
# 4. Конкретные Создатели
class EmailCreator(NotificationCreator):
def create_notification(self) -> Notification:
return EmailNotification()
class SmsCreator(NotificationCreator):
def create_notification(self) -> Notification:
return SmsNotification()
# --- Использование ---
def client_code(creator: NotificationCreator, message: str):
creator.send_notification(message)
# В зависимости от выбранной "фабрики", будет создан и использован нужный продукт
client_code(EmailCreator(), "Hello via Email!")
# Вывод: Отправка Email: Hello via Email!
client_code(SmsCreator(), "Hello via SMS!")
# Вывод: Отправка SMS: Hello via SMS!
Преимущества:
- Гибкость: Легко добавлять новые типы продуктов и их создателей.
- Слабая связанность: Код клиента работает с абстрактным создателем и продуктом, не зная их конкретных реализаций.
- Соблюдение принципа открытости/закрытости (OCP): Можно вводить новые типы продуктов, не изменяя существующий клиентский код.
Ответ 18+ 🔞
Смотри, паттерн "Фабричный метод" — это как если бы тебе, блядь, нужно было не просто взять и создать объект, а дать подумать об этом какому-то специальному чуваку. Он типа говорит: "Я создам тебе что-то, но не сам, а мой подкласс, который знает, какую конкретную хуйню тебе запилить".
Представь, что у тебя есть абстрактный класс NotificationCreator. Он как бы говорит: "Я умею отправлять уведомления, но вот конкретно что отправлять — пусть решает мой наследник". И вот этот наследник, конкретный создатель, уже говорит: "А, ну я-то знаю — надо EmailNotification" или "Нет, братан, тут SMSNotification нужен".
Вот смотри на код, тут всё чётко:
from abc import ABC, abstractmethod
# 1. Интерфейс Продукта
class Notification(ABC):
@abstractmethod
def send(self, message: str):
pass
# 2. Конкретные Продукты
class EmailNotification(Notification):
def send(self, message: str):
print(f"Отправка Email: {message}")
class SmsNotification(Notification):
def send(self, message: str):
print(f"Отправка SMS: {message}")
# 3. Абстрактный Создатель
class NotificationCreator(ABC):
@abstractmethod
def create_notification(self) -> Notification:
"""Это и есть Фабричный метод"""
pass
def send_notification(self, message: str):
notification = self.create_notification()
notification.send(message)
# 4. Конкретные Создатели
class EmailCreator(NotificationCreator):
def create_notification(self) -> Notification:
return EmailNotification()
class SmsCreator(NotificationCreator):
def create_notification(self) -> Notification:
return SmsNotification()
# --- Использование ---
def client_code(creator: NotificationCreator, message: str):
creator.send_notification(message)
# В зависимости от выбранной "фабрики", будет создан и использован нужный продукт
client_code(EmailCreator(), "Hello via Email!")
# Вывод: Отправка Email: Hello via Email!
client_code(SmsCreator(), "Hello via SMS!")
# Вывод: Отправка SMS: Hello via SMS!
Суть в том, что клиентский код (client_code) нихуя не знает, какой именно тип уведомления создаётся. Он просто говорит абстрактному создателю: "Эй, чувак, отправь сообщение". А тот уже внутри себя вызывает свой же фабричный метод create_notification(), который реализован в конкретном создателе. И вот этот конкретный создатель уже и решает, какую конкретную хуйню — email или sms — ему вернуть.
Преимущества, блядь, очевидны: если завтра понадобится добавить уведомление в Telegram, ты просто создашь новый класс TelegramNotification и новый создатель TelegramCreator. И ни один существующий код, ёпта, не придётся переписывать! Клиентский код как работал с абстракцией NotificationCreator, так и будет работать. Это и есть принцип открытости/закрытости в действии — открыто для расширения, закрыто для изменений. Красота, а не паттерн!