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

Опиши любой порождающий паттерн проектирования

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

Преимущества

  1. Слабая связанность — код не зависит от конкретных классов, только от интерфейсов.
  2. Легко расширять — добавление нового типа не требует изменения существующего кода (принцип Open/Closed).
  3. Централизованное создание — логика создания объектов в одном месте.
  4. Гибкость — легко менять реализацию на основе конфигурации или условий.

Недостатки

  1. Больше классов — для каждого типа нужен свой класс.
  2. Усложнение — может быть избыточным для простых случаев.
  3. Читаемость — при большом количестве типов структура может запутаться.

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

  • Когда типы объектов известны только во время выполнения
  • Когда нужно обеспечить расширяемость без изменения существующего кода
  • Когда логика создания сложная и зависит от многих факторов
  • Когда используются стратегии или плаги (plugin system)

Factory Method — один из самых популярных и полезных порождающих паттернов в реальных проектах.

Опиши любой порождающий паттерн проектирования | PrepBro