← Назад к вопросам
В чем разница между паттернами Фабрика и Абстрактная фабрика?
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
Сравнительная таблица
| Параметр | Factory | Abstract 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 более сложная, но обеспечивает лучшую масштабируемость и гибкость. Выбирай на основе сложности проекта.