← Назад к вопросам
Опиши любой порождающий паттерн проектирования
2.0 Middle🔥 191 комментариев
#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерн Factory Method (Фабричный метод)
Fatory Method — это порождающий паттерн, который определяет интерфейс для создания объектов, но оставляет подклассам решение о том, какой класс инстанцировать. Это позволяет подклассам переопределять метод создания и производить объекты нужного типа, не зависяя от конкретных реализаций.
Проблема
Представим систему доставки с разными видами транспорта (грузовик, самолёт, корабль). Если создавать объекты напрямую через конструктор, код будет содержать условия и плотно связан с конкретными классами.
# Плохо: жёсткая связанность
if transport_type == 'truck':
transport = Truck()
elif transport_type == 'plane':
transport = Plane()
elif transport_type == 'ship':
transport = Ship()
При добавлении нового вида транспорта нужно менять этот код везде.
Решение: Factory Method
from abc import ABC, abstractmethod
# 1. Интерфейс для всех видов транспорта
class Transport(ABC):
@abstractmethod
def deliver(self, cargo: str) -> str:
pass
# 2. Конкретные реализации
class Truck(Transport):
def deliver(self, cargo: str) -> str:
return f"Доставка {cargo} грузовиком по дороге"
class Plane(Transport):
def deliver(self, cargo: str) -> str:
return f"Доставка {cargo} самолётом по воздуху"
class Ship(Transport):
def deliver(self, cargo: str) -> str:
return f"Доставка {cargo} кораблём по морю"
# 3. Абстрактный класс с фабричным методом
class Logistics(ABC):
@abstractmethod
def create_transport(self) -> Transport:
"""Фабричный метод — подклассы его реализуют"""
pass
def plan_delivery(self, cargo: str) -> str:
transport = self.create_transport()
return transport.deliver(cargo)
# 4. Конкретные реализации логистики
class RoadLogistics(Logistics):
def create_transport(self) -> Transport:
return Truck()
class AirLogistics(Logistics):
def create_transport(self) -> Transport:
return Plane()
class SeaLogistics(Logistics):
def create_transport(self) -> Transport:
return Ship()
# Использование
logistics: Logistics = RoadLogistics()
print(logistics.plan_delivery("Посылка")) # Доставка Посылка грузовиком по дороге
logistics = AirLogistics()
print(logistics.plan_delivery("Посылка")) # Доставка Посылка самолётом по воздуху
logistics = SeaLogistics()
print(logistics.plan_delivery("Посылка")) # Доставка Посылка кораблём по морю
Практический пример: работа с БД
class DatabaseConnection(ABC):
@abstractmethod
def connect(self) -> str:
pass
class PostgresConnection(DatabaseConnection):
def connect(self) -> str:
return "Подключение к PostgreSQL"
class MongoConnection(DatabaseConnection):
def connect(self) -> str:
return "Подключение к MongoDB"
class MySQLConnection(DatabaseConnection):
def connect(self) -> str:
return "Подключение к MySQL"
# Конфигурируемая фабрика
class Database(ABC):
@abstractmethod
def create_connection(self) -> DatabaseConnection:
pass
def initialize(self) -> str:
connection = self.create_connection()
return connection.connect()
class PostgresDB(Database):
def create_connection(self) -> DatabaseConnection:
return PostgresConnection()
class MongoDB(Database):
def create_connection(self) -> DatabaseConnection:
return MongoConnection()
class MySQLDB(Database):
def create_connection(self) -> DatabaseConnection:
return MySQLConnection()
# Использование в конфиге приложения
db_type = "postgres" # Из конфига
if db_type == "postgres":
db = PostgresDB()
elif db_type == "mongo":
db = MongoDB()
else:
db = MySQLDB()
print(db.initialize()) # Подключение к PostgreSQL
Преимущества
- Слабая связанность — код не зависит от конкретных классов, только от интерфейсов.
- Легко расширять — добавление нового типа не требует изменения существующего кода (принцип Open/Closed).
- Централизованное создание — логика создания объектов в одном месте.
- Гибкость — легко менять реализацию на основе конфигурации или условий.
Недостатки
- Больше классов — для каждого типа нужен свой класс.
- Усложнение — может быть избыточным для простых случаев.
- Читаемость — при большом количестве типов структура может запутаться.
Когда использовать
- Когда типы объектов известны только во время выполнения
- Когда нужно обеспечить расширяемость без изменения существующего кода
- Когда логика создания сложная и зависит от многих факторов
- Когда используются стратегии или плаги (plugin system)
Factory Method — один из самых популярных и полезных порождающих паттернов в реальных проектах.