Как выбрать паттерн и не злоупотреблять

Финальный урок: как выбрать нужный паттерн, распознать злоупотребление и куда двигаться после курса.

Зрелость в паттернах — это не «знать все 23», а понимать, когда паттерн не нужен. Лучший паттерн часто — никакого.

Антипаттерны: чего избегать

Антипаттерн — типовое решение, которое выглядит разумным, но приносит больше вреда, чем пользы. Несколько частых:

АнтипаттернСимптом
God ObjectОдин класс знает и делает всё — нарушение SRP
Golden Hammer«Знаю Singleton — суну его везде»; один инструмент на все задачи
Pattern feverПаттерны ради паттернов: фабрика фабрик, прокси над прокси
Spaghetti / LasagnaЛибо хаос связей, либо столько слоёв абстракции, что не докопаться до логики

Алгоритм выбора паттерна

  1. Назови проблему. Что именно болит — создание объектов, склейка структур, взаимодействие? Это сразу даёт группу (см. урок о классификации).
  2. Проверь, есть ли изменчивость. Паттерн оправдан там, где будет меняться. Нет изменчивости — нет паттерна.
  3. Начни с простого. Функция, словарь, полиморфизм нередко решают задачу без «именного» паттерна.
  4. Применяй по «правилу трёх». Вводи паттерн, когда повторение стало реальным, а не гипотетическим.

Маленький «навигатор по симптомам» как памятка.

def suggest(symptom):
    rules = {
        "много if по типу": "Strategy или Factory Method",
        "нужно уведомлять многих": "Observer",
        "несовместимый чужой API": "Adapter",
        "сложная подсистема": "Facade",
        "undo/redo": "Command (+ Memento)",
        "дерево объектов": "Composite",
    }
    return rules.get(symptom, "возможно, паттерн не нужен")


for s in ["много if по типу", "нужно уведомлять многих",
          "undo/redo", "просто посчитать сумму"]:
    print(f"{s} -> {suggest(s)}")

Вывод:

много if по типу -> Strategy или Factory Method
нужно уведомлять многих -> Observer
undo/redo -> Command (+ Memento)
просто посчитать сумму -> возможно, паттерн не нужен

Обратите внимание на последнюю строку: для тривиальной задачи честный ответ — «паттерн не нужен». Это не поражение, а зрелость.

Признаки, что вы злоупотребляете

  • Чтобы понять простую логику, приходится прыгать по пяти классам.
  • Интерфейсы с единственной реализацией «на будущее», которое не наступает.
  • Имя паттерна в названии класса важнее, чем его польза (AbstractSingletonProxyFactoryBean).
  • Новый разработчик не может объяснить, зачем здесь этот слой.

Что дальше

Вы освоили словарь паттернов. Дальше углубляйтесь так:

  • Рефакторинг. Паттерны редко проектируют заранее — к ним рефакторят, когда боль проявилась (книга Фаулера «Рефакторинг»).
  • Принципы выше паттернов. SOLID, DRY, KISS, YAGNI — фундамент; паттерны лишь их инструменты.
  • Архитектурные паттерны. Следующий масштаб — MVC, слоистая архитектура, гексагональная, событийная, микросервисы.
  • Идиомы языка. В Python многие GoF-паттерны вырождаются в функции, декораторы, генераторы — учите идиомы своего языка.

Итог курса

  • Паттерн — инструмент против изменчивости, а не самоцель.
  • Выбор: назови проблему → проверь изменчивость → начни с простого → применяй по правилу трёх.
  • Зрелость — знать, когда паттерн НЕ нужен; дальше — рефакторинг, принципы и архитектура.
Проверьте себя
1. Что такое антипаттерн?
AПаттерн для асинхронного кода
BТиповое решение, которое выглядит разумным, но вредит больше, чем помогает
CПаттерн без интерфейса
DЛюбой неизвестный паттерн
2. С чего стоит начинать выбор решения?
AСразу выбрать самый сложный паттерн
BНазвать проблему и проверить, есть ли реальная изменчивость
CДобавить интерфейсы на будущее
DСделать всё синглтонами
3. Какой главный признак зрелости в работе с паттернами?
AЗнать наизусть все 23
BПонимать, когда паттерн НЕ нужен
CИспользовать паттерн в каждом классе
DДавать классам имена паттернов
Поддержать проект