Factory Method

Паттерн, который отвечает за вопрос «какой именно класс создать», не заставляя клиента знать про конкретные типы.

Factory Method определяет интерфейс для создания объекта, но позволяет подклассам (или конфигурации) решать, какой конкретный класс инстанцировать.

Какую задачу решает

Клиентский код хочет «транспорт», «документ», «кнопку» — но не должен зависеть от конкретного класса Truck или PdfDocument. Если разбросать if тип == "pdf": ... по всему проекту, добавление нового типа превратится в охоту по файлам. Factory Method собирает решение «что создать» в одном месте.

Идея и реализация

Заведём общий интерфейс продукта и фабричную функцию, которая по ключу возвращает нужную реализацию. Клиент работает с интерфейсом.

from abc import ABC, abstractmethod


class Transport(ABC):
    @abstractmethod
    def deliver(self):
        ...


class Truck(Transport):
    def deliver(self):
        return "доставка по дороге"


class Ship(Transport):
    def deliver(self):
        return "доставка по морю"


def create_transport(kind: str) -> Transport:
    registry = {"truck": Truck, "ship": Ship}
    if kind not in registry:
        raise ValueError(f"неизвестный транспорт: {kind}")
    return registry[kind]()        # фабрика решает, какой класс создать


for kind in ("truck", "ship"):
    t = create_transport(kind)
    print(kind, "->", t.deliver())

Вывод:

truck -> доставка по дороге
ship -> доставка по морю

Добавить самолёт — это новый класс Plane и одна строчка в registry. Клиентский цикл не меняется: он по-прежнему вызывает create_transport и deliver. Это прямое следствие принципа Open/Closed.

Класс-вариант

Каноническая (GoF) форма — фабричный метод в базовом классе, который переопределяют подклассы. Например, у Dialog есть метод create_button(), а WindowsDialog и WebDialog возвращают из него свою кнопку. В Python чаще используют функцию или регистр, как выше, — это проще и идиоматичнее.

Плюсы и минусы

ПлюсыМинусы
Убирает разбросанные if по типуЕщё один слой косвенности
Соблюдает OCP — новый тип не ломает клиентаДля одного-двух типов может быть избыточен
Изолирует логику создания

Где встречается

Парсеры, выбирающие обработчик по формату файла; logging-handlers; драйверы БД, выбираемые по строке подключения; во фреймворках — создание объектов по конфигу.

Итог

  • Factory Method централизует решение «какой класс создать».
  • Клиент зависит от интерфейса продукта, а не от конкретных классов.
  • В Python обычно реализуется функцией/регистром, а не иерархией классов.
Проверьте себя
1. Какую проблему решает Factory Method?
AУскоряет сортировку
BУбирает разбросанный по коду выбор конкретного класса
CГарантирует один экземпляр
DКеширует результаты
2. Какому принципу SOLID прежде всего служит Factory Method?
ALiskov Substitution
BOpen/Closed
CInterface Segregation
DНикакому
3. Что вернёт фабрика клиенту?
AКонкретный класс Truck напрямую
BОбъект, реализующий общий интерфейс продукта
CСтроку с именем класса
DСловарь настроек
Поддержать проект