Что такое паттерн Factory и зачем он нужен?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерн Factory
Factory Pattern — это порождающий паттерн проектирования, который предоставляет интерфейс для создания объектов без указания их конкретных классов. Вместо использования new напрямую, используется фабрика.
Зачем нужен Factory?
Проблема без Factory:
# Плохо — зависимость от конкретных классов
class DatabaseConnection:
def __init__(self, db_type):
if db_type == "postgresql":
self.connection = PostgreSQLConnection()
elif db_type == "mysql":
self.connection = MySQLConnection()
elif db_type == "mongodb":
self.connection = MongoDBConnection()
else:
raise ValueError("Unknown database type")
Проблемы:
- Жёсткая связанность
- Нарушение принципа Open/Closed (в SOLID)
- Сложно тестировать
- Код загромождается условиями
Решение с Factory
from abc import ABC, abstractmethod
# Абстракция
class Database(ABC):
@abstractmethod
def connect(self):
pass
@abstractmethod
def query(self, sql):
pass
# Конкретные реализации
class PostgreSQLDatabase(Database):
def connect(self):
print("Подключение к PostgreSQL")
def query(self, sql):
print(f"Выполнение запроса: {sql}")
class MySQLDatabase(Database):
def connect(self):
print("Подключение к MySQL")
def query(self, sql):
print(f"Выполнение запроса в MySQL: {sql}")
class MongoDBDatabase(Database):
def connect(self):
print("Подключение к MongoDB")
def query(self, sql):
print(f"Выполнение запроса в MongoDB: {sql}")
# Factory
class DatabaseFactory:
@staticmethod
def create(db_type: str) -> Database:
factories = {
"postgresql": PostgreSQLDatabase,
"mysql": MySQLDatabase,
"mongodb": MongoDBDatabase,
}
if db_type not in factories:
raise ValueError(f"Unknown database type: {db_type}")
return factories[db_type]()
# Использование
db = DatabaseFactory.create("postgresql")
db.connect()
db.query("SELECT * FROM users")
Типы Factory
1. Simple Factory (Простая фабрика)
class PaymentFactory:
@staticmethod
def create_payment(payment_type: str):
if payment_type == "credit_card":
return CreditCardPayment()
elif payment_type == "paypal":
return PayPalPayment()
elif payment_type == "stripe":
return StripePayment()
else:
raise ValueError("Unknown payment type")
# Использование
payment = PaymentFactory.create_payment("credit_card")
payment.process(100)
2. Factory Method (Метод фабрики)
from abc import ABC, abstractmethod
# Абстрактный класс с методом фабрики
class PaymentProcessor(ABC):
@abstractmethod
def create_payment(self):
pass
def process_order(self, amount):
payment = self.create_payment()
payment.process(amount)
print(f"Заказ на {amount} обработан")
# Конкретные реализации
class CreditCardProcessor(PaymentProcessor):
def create_payment(self):
return CreditCardPayment()
class PayPalProcessor(PaymentProcessor):
def create_payment(self):
return PayPalPayment()
# Использование
processor = CreditCardProcessor()
processor.process_order(100)
3. Abstract Factory (Абстрактная фабрика)
from abc import ABC, abstractmethod
# Интерфейсы для UI компонентов
class Button(ABC):
@abstractmethod
def render(self):
pass
class Input(ABC):
@abstractmethod
def render(self):
pass
# Конкретные реализации для Windows
class WindowsButton(Button):
def render(self):
print("Рисую кнопку в стиле Windows")
class WindowsInput(Input):
def render(self):
print("Рисую input в стиле Windows")
# Конкретные реализации для macOS
class MacButton(Button):
def render(self):
print("Рисую кнопку в стиле macOS")
class MacInput(Input):
def render(self):
print("Рисую input в стиле macOS")
# Abstract Factory
class UIFactory(ABC):
@abstractmethod
def create_button(self) -> Button:
pass
@abstractmethod
def create_input(self) -> Input:
pass
# Конкретные фабрики
class WindowsUIFactory(UIFactory):
def create_button(self):
return WindowsButton()
def create_input(self):
return WindowsInput()
class MacUIFactory(UIFactory):
def create_button(self):
return MacButton()
def create_input(self):
return MacInput()
# Использование
factory = WindowsUIFactory()
button = factory.create_button()
input_field = factory.create_input()
Factory в Django
Django интенсивно использует Factory:
from django.db import models
class User(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
# User.objects — это Manager (фабрика объектов User)
users = User.objects.all()
user = User.objects.get(id=1)
user = User.objects.create(name="John", email="john@example.com")
Factory в Python с dataclasses
from dataclasses import dataclass
@dataclass
class Config:
host: str
port: int
debug: bool
class ConfigFactory:
@staticmethod
def create_dev() -> Config:
return Config(host="localhost", port=8000, debug=True)
@staticmethod
def create_prod() -> Config:
return Config(host="0.0.0.0", port=80, debug=False)
@staticmethod
def create_test() -> Config:
return Config(host="localhost", port=5432, debug=False)
# Использование
dev_config = ConfigFactory.create_dev()
prod_config = ConfigFactory.create_prod()
Преимущества Factory
✅ Слабая связанность — код не зависит от конкретных классов
✅ Легко расширять — добавить новый тип без изменения существующего кода
✅ Централизованное управление — логика создания в одном месте
✅ Тестируемость — легко подставить mock-объекты
✅ Принцип Open/Closed — открыт для расширения, закрыт для модификации
Недостатки
❌ Усложнение кода — дополнительные классы и интерфейсы
❌ Overkill для простых случаев — если типов 1-2, Factory может быть лишним
Когда использовать Factory
- Множество похожих объектов (БД, платежные системы, UI)
- Логика создания сложная
- Объекты часто меняют тип
- Нужна гибкость в выборе реализации
Выводы
Factory Pattern — это способ организовать создание объектов так, чтобы отделить создание от использования, облегчить расширение и обеспечить слабую связанность компонентов.