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

В чем разница между паттернами Фабрика и Абстрактная фабрика?

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

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

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

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

Разница между паттернами Фабрика и Абстрактная фабрика

Оба паттерна решают проблему создания объектов, но на разных уровнях абстракции. Это критически важное различие для интервью.

Определения

Factory (простая фабрика):

  • Создает объекты одного типа
  • На основе параметра решает, какой класс создать
  • Простая логика выбора

Abstract Factory:

  • Создает семейства связанных объектов
  • Обеспечивает интерфейс для создания целых наборов
  • Сложная логика выбора

Пример 1: Simple Factory

class Dog:
    def speak(self):
        return "Woof!"

class Cat:
    def speak(self):
        return "Meow!"

class Bird:
    def speak(self):
        return "Tweet!"

# Simple Factory
class AnimalFactory:
    @staticmethod
    def create_animal(animal_type: str):
        if animal_type == 'dog':
            return Dog()
        elif animal_type == 'cat':
            return Cat()
        elif animal_type == 'bird':
            return Bird()
        else:
            raise ValueError(f"Unknown animal type: {animal_type}")

# Использование
animal = AnimalFactory.create_animal('dog')
print(animal.speak())  # Woof!

Плюсы:

  • Простая и быстрая в реализации
  • Логика создания в одном месте

Минусы:

  • Сложные условия с много if/elif
  • Дарде добавлять новые типы
  • Не масштабируется

Пример 2: Abstract Factory

from abc import ABC, abstractmethod

# Интерфейсы для создания семейств объектов
class Button(ABC):
    @abstractmethod
    def render(self):
        pass

class Input(ABC):
    @abstractmethod
    def render(self):
        pass

# Конкретные реализации для MacOS
class MacButton(Button):
    def render(self):
        return "Рисую кнопку в стиле MacOS"

class MacInput(Input):
    def render(self):
        return "Рисую input в стиле MacOS"

# Конкретные реализации для Windows
class WindowsButton(Button):
    def render(self):
        return "Рисую кнопку в стиле Windows"

class WindowsInput(Input):
    def render(self):
        return "Рисую input в стиле Windows"

# Абстрактная фабрика
class UIFactory(ABC):
    @abstractmethod
    def create_button(self) -> Button:
        pass
    
    @abstractmethod
    def create_input(self) -> Input:
        pass

# Конкретные фабрики
class MacFactory(UIFactory):
    def create_button(self) -> Button:
        return MacButton()
    
    def create_input(self) -> Input:
        return MacInput()

class WindowsFactory(UIFactory):
    def create_button(self) -> Button:
        return WindowsButton()
    
    def create_input(self) -> Input:
        return WindowsInput()

# Использование
def create_ui(factory: UIFactory):
    button = factory.create_button()
    input_field = factory.create_input()
    
    print(button.render())
    print(input_field.render())

# Клиент не знает о конкретных классах
factory = MacFactory()
create_ui(factory)
# Рисую кнопку в стиле MacOS
# Рисую input в стиле MacOS

factory = WindowsFactory()
create_ui(factory)
# Рисую кнопку в стиле Windows
# Рисую input в стиле Windows

Сравнительная таблица

ПараметрFactoryAbstract Factory
СоздаетОдин тип объектовСемейство объектов
Количество методов1-2Много
Уровень сложностиПростойСредний/Сложный
ИнтерфейсыНетДа, много интерфейсов
МасштабируемостьПлохаяХорошая
Количество классовНебольшоеМного
Когда использоватьПростое созданиеСемейства продуктов

Визуальное сравнение

Factory (простая):

AnimalFactory
    ├── create() -> Dog
    ├── create() -> Cat
    └── create() -> Bird

Abstract Factory:

UIFactory (интерфейс)
    ├── create_button() -> Button
    └── create_input() -> Input
        ├── MacFactory
        │   ├── MacButton
        │   └── MacInput
        └── WindowsFactory
            ├── WindowsButton
            └── WindowsInput

Более сложный пример

# Например, создание таблиц для разных БД

from abc import ABC, abstractmethod

class Query(ABC):
    @abstractmethod
    def build(self) -> str:
        pass

class SelectQuery(Query):
    def build(self) -> str:
        return "SELECT * FROM table"

class InsertQuery(Query):
    def build(self) -> str:
        return "INSERT INTO table VALUES (...)"

# PostgreSQL
class PostgreSQLSelect(SelectQuery):
    def build(self) -> str:
        return "SELECT * FROM table;"  # С точкой с запятой

class PostgreSQLInsert(InsertQuery):
    def build(self) -> str:
        return "INSERT INTO table VALUES (...) RETURNING id;"  # С RETURNING

# MySQL
class MySQLSelect(SelectQuery):
    def build(self) -> str:
        return "SELECT * FROM table LIMIT 1000;"  # С LIMIT

class MySQLInsert(InsertQuery):
    def build(self) -> str:
        return "INSERT INTO table VALUES (...) ON DUPLICATE KEY UPDATE;"  # На DUPLICATE

# Фабрика
class DatabaseFactory(ABC):
    @abstractmethod
    def create_select(self) -> SelectQuery:
        pass
    
    @abstractmethod
    def create_insert(self) -> InsertQuery:
        pass

class PostgreSQLFactory(DatabaseFactory):
    def create_select(self) -> SelectQuery:
        return PostgreSQLSelect()
    
    def create_insert(self) -> InsertQuery:
        return PostgreSQLInsert()

class MySQLFactory(DatabaseFactory):
    def create_select(self) -> SelectQuery:
        return MySQLSelect()
    
    def create_insert(self) -> InsertQuery:
        return MySQLInsert()

# Использование
def execute_queries(factory: DatabaseFactory):
    select = factory.create_select()
    insert = factory.create_insert()
    
    print(select.build())
    print(insert.build())

execute_queries(PostgreSQLFactory())
# SELECT * FROM table;
# INSERT INTO table VALUES (...) RETURNING id;

execute_queries(MySQLFactory())
# SELECT * FROM table LIMIT 1000;
# INSERT INTO table VALUES (...) ON DUPLICATE KEY UPDATE;

Когда использовать

Simple Factory, когда:

  • Мало типов объектов (2-3)
  • Простая логика выбора
  • Редко добавляются новые типы
class LoggerFactory:
    @staticmethod
    def create_logger(log_type):
        if log_type == 'file':
            return FileLogger()
        elif log_type == 'console':
            return ConsoleLogger()

Abstract Factory, когда:

  • Много связанных типов (группы объектов)
  • Часто добавляются новые комбинации
  • Нужна гибкость и масштабируемость
  • Клиент не должен знать о конкретных классах

Практический пример из реальности

# ORM для разных БД
class Session(ABC):
    @abstractmethod
    def query(self, model):
        pass

class DatabaseFactory(ABC):
    @abstractmethod
    def create_session(self) -> Session:
        pass

# SQLAlchemy использует этот паттерн для поддержки
# PostgreSQL, MySQL, SQLite, Oracle одновременно

Заключение

Factory (простая) - это когда нужно выбрать один из нескольких типов.

Abstract Factory - это когда нужно создать целое семейство связанных объектов и гарантировать, что они совместимы друг с другом.

Abstract Factory более сложная, но обеспечивает лучшую масштабируемость и гибкость. Выбирай на основе сложности проекта.