← Назад к вопросам
Что ожидается на выходе у шаблона фабрика?
1.3 Junior🔥 101 комментариев
#DevOps и инфраструктура
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что ожидается на выходе у шаблона Фабрика
Factory Pattern (Фабрика) — один из основных паттернов проектирования. Это паттерн для создания объектов без указания их точных классов. Рассмотрю все его варианты и результаты.
1. Simple Factory (Простая фабрика)
На выходе: Один объект нужного типа в зависимости от параметра.
from abc import ABC, abstractmethod
# Определяем интерфейс
class Transport(ABC):
@abstractmethod
def deliver(self) -> str:
pass
# Конкретные классы
class Car(Transport):
def deliver(self) -> str:
return "Доставка машиной по дороге"
class Ship(Transport):
def deliver(self) -> str:
return "Доставка кораблём по морю"
class Plane(Transport):
def deliver(self) -> str:
return "Доставка самолётом по воздуху"
# ФАБРИКА — возвращает нужный объект
class TransportFactory:
@staticmethod
def create_transport(transport_type: str) -> Transport:
"""На выходе: объект нужного класса"""
if transport_type == "car":
return Car()
elif transport_type == "ship":
return Ship()
elif transport_type == "plane":
return Plane()
else:
raise ValueError(f"Неизвестный тип: {transport_type}")
# Использование
factory = TransportFactory()
transport = factory.create_transport("car") # На выходе: объект Car
print(transport.deliver()) # "Доставка машиной по дороге"
На выходе:
- ✅ Объект нужного типа
- ✅ Имплементирует общий интерфейс
- ✅ Готов к использованию
2. Factory Method (Метод фабрика)
На выходе: Объект, созданный через виртуальный метод подклассов.
from abc import ABC, abstractmethod
# Интерфейс для фабрики
class Creator(ABC):
@abstractmethod
def create_product(self):
"""Метод фабрика — должен вернуть Product"""
pass
def business_logic(self):
"""Бизнес-логика использует результат фабрики"""
product = self.create_product() # На выходе: нужный Product
return f"Creator работает с {product.operation()}"
# Интерфейс для продукта
class Product(ABC):
@abstractmethod
def operation(self) -> str:
pass
# Конкретные создатели
class ConcreteCreatorA(Creator):
def create_product(self) -> Product:
"""На выходе: ConcreteProductA"""
return ConcreteProductA()
class ConcreteCreatorB(Creator):
def create_product(self) -> Product:
"""На выходе: ConcreteProductB"""
return ConcreteProductB()
# Конкретные продукты
class ConcreteProductA(Product):
def operation(self) -> str:
return "Результат продукта A"
class ConcreteProductB(Product):
def operation(self) -> str:
return "Результат продукта B"
# Использование
creator_a = ConcreteCreatorA()
print(creator_a.business_logic()) # На выходе: ConcreteProductA
creator_b = ConcreteCreatorB()
print(creator_b.business_logic()) # На выходе: ConcreteProductB
На выходе:
- ✅ Product нужного типа
- ✅ Выбор типа делегирован подклассу
- ✅ Слабая связанность
3. Abstract Factory (Абстрактная фабрика)
На выходе: Семейство связанных объектов.
from abc import ABC, abstractmethod
# СЕМЕЙСТВО ПРОДУКТОВ 1
class Button(ABC):
@abstractmethod
def paint(self) -> str:
pass
class Checkbox(ABC):
@abstractmethod
def paint(self) -> str:
pass
# Windows реализация
class WindowsButton(Button):
def paint(self) -> str:
return "Отрисовка Windows кнопки"
class WindowsCheckbox(Checkbox):
def paint(self) -> str:
return "Отрисовка Windows чекбокса"
# Mac реализация
class MacButton(Button):
def paint(self) -> str:
return "Отрисовка Mac кнопки"
class MacCheckbox(Checkbox):
def paint(self) -> str:
return "Отрисовка Mac чекбокса"
# АБСТРАКТНАЯ ФАБРИКА
class GUIFactory(ABC):
@abstractmethod
def create_button(self) -> Button:
pass
@abstractmethod
def create_checkbox(self) -> Checkbox:
pass
# Конкретные фабрики
class WindowsFactory(GUIFactory):
def create_button(self) -> Button:
return WindowsButton() # На выходе: WindowsButton
def create_checkbox(self) -> Checkbox:
return WindowsCheckbox() # На выходе: WindowsCheckbox
class MacFactory(GUIFactory):
def create_button(self) -> Button:
return MacButton() # На выходе: MacButton
def create_checkbox(self) -> Checkbox:
return MacCheckbox() # На выходе: MacCheckbox
# Использование
def render_ui(factory: GUIFactory):
"""На выходе фабрики: СОГЛАСОВАННОЕ СЕМЕЙСТВО объектов"""
button = factory.create_button()
checkbox = factory.create_checkbox()
print(button.paint())
print(checkbox.paint())
# На выходе всей функции: согласованный UI
windows_factory = WindowsFactory()
render_ui(windows_factory)
# На выходе: WindowsButton + WindowsCheckbox (согласованы!)
mac_factory = MacFactory()
render_ui(mac_factory)
# На выходе: MacButton + MacCheckbox (согласованы!)
На выходе:
- ✅ Семейство связанных объектов
- ✅ Все объекты из одного "семейства" (Windows/Mac)
- ✅ Гарантирована совместимость
4. Практический пример: Система логирования
from abc import ABC, abstractmethod
from typing import Any
# Интерфейсы
class Logger(ABC):
@abstractmethod
def log(self, message: str) -> None:
pass
class Handler(ABC):
@abstractmethod
def handle(self, record: dict) -> None:
pass
# Конкретные логгеры
class ConsoleLogger(Logger):
def log(self, message: str) -> None:
print(f"[CONSOLE] {message}")
class FileLogger(Logger):
def __init__(self, filename: str = "app.log"):
self.filename = filename
def log(self, message: str) -> None:
with open(self.filename, "a") as f:
f.write(f"[FILE] {message}\\n")
class DatabaseLogger(Logger):
def log(self, message: str) -> None:
# Имитация сохранения в БД
print(f"[DB] Сохраняю в базу: {message}")
# ФАБРИКА ЛОГГЕРОВ
class LoggerFactory:
_loggers = {
"console": ConsoleLogger,
"file": FileLogger,
"database": DatabaseLogger,
}
@classmethod
def create_logger(cls, logger_type: str, **kwargs) -> Logger:
"""На выходе: объект Logger нужного типа"""
if logger_type not in cls._loggers:
raise ValueError(f"Неизвестный тип логгера: {logger_type}")
logger_class = cls._loggers[logger_type]
return logger_class(**kwargs) # На выходе!
@classmethod
def register_logger(cls, name: str, logger_class: type) -> None:
"""Возможность расширить фабрику"""
cls._loggers[name] = logger_class
# Использование
logger = LoggerFactory.create_logger("console") # На выходе: ConsoleLogger
logger.log("Это сообщение в консоль")
file_logger = LoggerFactory.create_logger("file", filename="debug.log") # На выходе: FileLogger
file_logger.log("Это сообщение в файл")
db_logger = LoggerFactory.create_logger("database") # На выходе: DatabaseLogger
db_logger.log("Это сообщение в БД")
5. Фабрика в реальных проектах
# Django ORM: Фабрика для создания моделей
from django.db import models
class User(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
# На выходе: объект User из БД
user = User.objects.get(id=1) # Фабрика!
users = User.objects.filter(email__contains="gmail") # Фабрика!
# SQLAlchemy Session: Фабрика для сессий
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
engine = create_engine("postgresql://user:password@localhost/db")
SessionFactory = sessionmaker(bind=engine)
# На выходе: новая сессия
session = SessionFactory() # Фабрика!
user = session.query(User).get(1)
# FastAPI dependency injection: Фабрика для зависимостей
from fastapi import Depends, FastAPI
app = FastAPI()
def get_db():
"""Фабрика для БД сессий"""
db = SessionLocal()
try:
yield db # На выходе: сессия БД
finally:
db.close()
@app.get("/users/{user_id}")
def get_user(user_id: int, db = Depends(get_db)): # На выходе: db сессия
return db.query(User).get(user_id)
Сравнение типов фабрик
| Тип | На выходе | Когда использовать |
|---|---|---|
| Simple Factory | Один объект | Простая логика выбора типа |
| Factory Method | Один объект (через подклассы) | Разные подклассы создают разные объекты |
| Abstract Factory | Семейство объектов | Связанные семейства (Windows/Mac) |
Ключевые свойства на выходе
class FactoryPattern:
"""
Что всегда должно быть на выходе фабрики?
"""
@staticmethod
def expectations():
return {
'type': 'Объект нужного класса или интерфейса',
'ready_to_use': 'Полностью инициализирован',
'interface': 'Реализует нужный контракт (ABC)',
'no_client_knowledge': 'Клиент не знает точный тип',
'extensible': 'Легко добавлять новые типы',
'decoupled': 'Низкая связанность с кодом',
}
Итоговый ответ
На выходе фабрики ожидается:
- Объект нужного типа (готовый к использованию)
- Реализация общего интерфейса (Abstract Base Class)
- Отсутствие прямой зависимости от конкретного класса
- Гибкость — легко добавлять новые типы
- Инкапсуляция логики создания объектов
Фабрика скрывает сложность создания и позволяет менять реализацию без изменения кода, который её использует. Это основной смысл паттерна.