← Назад к вопросам

Что такое паттерн Factory и зачем он нужен?

1.7 Middle🔥 201 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Паттерн 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")

Проблемы:

  1. Жёсткая связанность
  2. Нарушение принципа Open/Closed (в SOLID)
  3. Сложно тестировать
  4. Код загромождается условиями

Решение с 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 — это способ организовать создание объектов так, чтобы отделить создание от использования, облегчить расширение и обеспечить слабую связанность компонентов.

Что такое паттерн Factory и зачем он нужен? | PrepBro