Перейти к содержанию

Порождающие паттерны (Creational Patterns)

Какую проблему решает эта категория

Порождающие паттерны отвечают на один вопрос: как создавать объекты так, чтобы код, который их создаёт, не был жёстко привязан к конкретным классам этих объектов.

Самый простой способ создать объект в C# - оператор new SomeClass(). Но у прямого new есть скрытая цена:

  • код, вызвавший new, теперь знает и зависит от конкретного типа SomeClass, а не от абстракции;
  • если логика создания объекта усложняется (нужно выбрать один из нескольких классов, собрать объект из многих частей, переиспользовать уже созданный экземпляр), эта логика начинает дублироваться по всему проекту в местах, где вызывается new;
  • становится сложно подменить реализацию в тестах (замокать) или изменить её в рантайме.

Порождающие паттерны инкапсулируют логику создания объектов в одном месте (метод, класс, отдельная фабрика), а остальной код работает с результатом через абстракцию, ничего не зная о том, как объект был создан.

Что объединяет паттерны из этой папки

Паттерн Ключевая идея
Singleton Контролирует количество экземпляров - их должен быть ровно один
Factory Method Откладывает выбор конкретного класса создаваемого объекта до подкласса
Abstract Factory Создаёт согласованное семейство связанных объектов
Builder Разделяет процесс сборки сложного объекта и его конечное представление
Prototype Создаёт объект копированием готового прототипа, не зная его конкретного класса

Когда об этой категории стоит вспомнить

  • Логика выбора или сборки объекта содержит условия (if/switch по типу) и повторяется в разных местах кода.
  • Создание объекта требует много параметров, часть из которых опциональна.
  • Нужно ограничить количество экземпляров класса (конфигурация, кеш, логгер).
  • Система должна работать с разными семействами взаимосвязанных объектов (например, набор UI-контролов под разные темы), и важно не смешивать компоненты из разных семейств.
  • Есть дорогие или сложно настроенные объекты, которые проще клонировать из готовых эталонов → Prototype.

Важная оговорка для .NET

Часть задач, которые в классическом ООП решались порождающими паттернами, в современном .NET закрываются стандартными механизмами платформы:

  • DI-контейнер (Microsoft.Extensions.DependencyInjection) во многом берёт на себя роль Factory/Abstract Factory и управление временем жизни объектов (в том числе Singleton-семантику через AddSingleton);
  • Lazy<T> упрощает ленивую инициализацию, на которой построен классический Singleton;
  • object initializers, именованные и опциональные параметры в конструкторах снижают потребность в Builder для простых случаев.
  • record и выражение with дают удобный синтаксис неглубокого копирования, но не отменяют необходимость явно продумывать глубокую копию изменяемых ссылок в Prototype.

Тем не менее сами идеи (разделение "что создаём" и "как используем", сборка сложных объектов по шагам, семейства связанных объектов) остаются актуальными - меняется лишь конкретный синтаксис их выражения на C#.