Отвечают за удобное и безопасное создание новых объектов или даже целых семейств объектов. ### Фабричный метод Также известен как: Виртуальный конструктор, Factory Method [ссылка](https://refactoring.guru/ru/design-patterns/factory-method) Паттерн фабричный метод предоставляет интерфейс для создания объектов в суперклассе, но позволяет подклассам изменять тип создаваемых объектов. Фабричный метод отделяет код создания объектов от кода, который использует эти объекты. Это означает, что вместо вызова конструктора напрямую, вызывается метод (обычно абстрактный в базовом классе), который в свою очередь создает объект. ##### Пример GPT4 Представим, что у тебя есть абстрактный класс "Комната", и два конкретных класса "ОбычнаяКомната" и "БоссКомната". В классе "Комната" есть метод "создатьВрага", который определен как абстрактный. Теперь в каждом из подклассов ты переопределяешь этот метод, чтобы в "ОбычнаяКомната" создавался "ОбычныйВраг", а в "БоссКомната" - "Босс". Теперь, когда ты работаешь с объектом класса "Комната", ты просто вызываешь метод "создатьВрага", и, в зависимости от того, какой это конкретно объект ("ОбычнаяКомната" или "БоссКомната"), будет создан соответствующий враг. Паттерн фабричный метод обеспечивает гибкость в выборе конкретного класса объекта для создания, и поддерживает принцип открытости/закрытости, так как можно легко добавить новые подклассы и соответствующие фабричные методы без изменения существующего кода, который использует суперкласс. <br> ### Абстрактная фабрика Также известен как: Abstract Factory [ссылка](https://refactoring.guru/ru/design-patterns/abstract-factory) Паттерн показывает, что можно создавать абстрактные фабрики, каждая из которых создает разные виды абстрактных продуктов (сущности/экземпляры классов). Каждая фабрика объединяет в себе семейство абстрактных продуктов. ##### Что за семейство такое? Допустим, есть абстрактная фабрика по производству абстрактных: конфет, шоколадок и леденцов. Одна фабрика будет выпускать такие виды продуктов солеными, другая фабрика будет выпускать с корицей. Получается, что фабрика объединяет выпускаемые продукты в одно семейство. Первом случае семейство «соленых», а во втором случае «кориц». ##### Мой пример В интерфейсе абстрактной фабрики ты определяешь, допустим, 3 метода, каждая из которых возвращает определенный абстрактный продукт. Абстрактный продукт = один интерфейс под каждый продукт. Допустим, ты создаешь 10 разных конкретных фабрик, которые реализуют единый интерфейс абстрактной фабрики. Каждая из этих конкретных фабрик создает 3 разных продукта, одного семейства. Теперь ты можешь, в зависимости от контекста, менять фабрику, которая будет выдавать нужное семейство продуктов. С продуктами ты взаимодействуешь через интерфейсы продуктов. Такой подход создает модульность. Можно написать любую фабрику, которая создает любой продукт и тебе не нужно расширять код, который будет пользоваться новым продуктом. ```csharp class Client { public void Main() { // Клиентский код может работать с любым конкретным классом фабрики. Console.WriteLine("Client: Testing client code with the first factory"); ClientMethod(new ConcreteFactory1()); Console.WriteLine(); Console.WriteLine("Client: Testing the same client code with the second factory"); ClientMethod(new ConcreteFactory2()); } public void ClientMethod(IAbstractFactory factory) { var productA = factory.CreateProductA(); var productB = factory.CreateProductB(); Console.WriteLine(productB.UsefulFunctionB()); Console.WriteLine(productB.AnotherUsefulFunctionB(productA)); } } ``` ##### Пример GPT4 Представим, что ты создаешь игру и у тебя есть несколько различных тем (например, "Космическая" и "Медиевальная"). Каждая тема имеет свой набор объектов, таких как "фон", "герой" и "враг". Ты определяешь абстрактную фабрику "Тема", которая может создавать продукты "фон", "герой" и "враг". Затем ты создаешь конкретные фабрики "КосмическаяТема" и "МедиевальнаяТема", которые реализуют эту абстрактную фабрику и производят соответствующие продукты. При смене темы во время выполнения, ты просто меняешь активную фабрику и продолжаешь вызывать методы создания продуктов, получая объекты, соответствующие новой теме. Абстрактная фабрика позволяет обеспечить согласованность между связанными продуктами, так что ты не можешь, например, случайно создать "Космического героя" в "Медиевальной" теме. Это также обеспечивает гибкость в замене и добавлении новых семейств продуктов. ##### Разница между "Фабричным методом" и "Абстрактной фабрикой" Это действительно может вызвать путаницу, так как оба этих паттерна относятся к созданию объектов и имеют схожую структуру. Однако есть несколько ключевых отличий: 1. **Цель создания**:
Фабричный метод обычно используется для создания одного объекта, который вписывается в определенный интерфейс или базовый класс, но имеет различные реализации. Основное внимание уделяется вариативности конкретного продукта.
Абстрактная фабрика используется для создания семейств взаимосвязанных или взаимозависимых объектов. Здесь акцент смещен на создание целого набора взаимосвязанных продуктов (набора продуктов, которые вместе работают правильно). 2. **Структура**:
Фабричный метод обычно содержит один метод создания, который возвращает один тип продукта.
Абстрактная фабрика представляет собой интерфейс с несколькими методами создания, каждый из которых создает разный тип продукта. 3. **Сложность**:
Фабричный метод — это более простой и базовый шаблон проектирования, который легче понять и реализовать.
Абстрактная фабрика — это более сложный шаблон, который используется для более сложных задач, где необходимо создавать семейства объектов, работающих вместе. В итоге, когда вы создаете один тип объекта, используйте фабричный метод. Когда вам нужно создать семейство взаимосвязанных или взаимозависимых объектов, используйте абстрактную фабрику. ### Строитель Также известен как: Builder [ссылка](https://refactoring.guru/ru/design-patterns/builder) Позволяет создавать сложные экземпляры пошагово. Строитель даёт возможность использовать один и тот же код строительства для получения разных представлений экземпляров. Паттерн Строитель предлагает вынести конструирование экземпляра за пределы его собственного класса, поручив это дело отдельным типам, называемым *строителями*. Паттерн предлагает разбить процесс конструирования объекта на отдельные шаги (например, построитьСтены, вставитьДвери и другие). Чтобы создать экземпляр, вам нужно поочерёдно вызывать методы строителя. Причём не нужно запускать все шаги, а только те, что нужны для производства экземпляра определённой конфигурации. <u>Как дополнительная опция! </u> Зачастую один и тот же шаг строительства может отличаться для разных вариаций производимых экземпляров. Например, деревянный дом потребует строительства стен из дерева, а каменный — из камня. В этом случае вы можете создать несколько классов строителей, выполняющих одни и те же шаги по-разному. Используя этих строителей в одном и том же строительном процессе, вы сможете получать на выходе различные экземпляры. ##### Пример GPT4 Представь, что ты создаешь разные виды игровых персонажей (например, рыцарь, волшебник, лучник). Каждый из этих персонажей имеет свой набор характеристик и способностей, которые могут быть сложными для создания и настройки. Ты определяешь "СтроителяПерсонажа", который имеет методы для установки каждой из этих характеристик и способностей. Затем ты можешь создать конкретные строители (например, "СтроительРыцаря", "СтроительВолшебника", "СтроительЛучника") и использовать их для создания и настройки персонажей пошагово. Теперь вводится роль "Директора". "Директор" знает в каком порядке должны быть вызваны методы строителя для создания конкретного типа персонажа. Например, для рыцаря сначала надо установить броню, затем меч, затем силу и так далее. Когда персонаж полностью готов, "Директор" вызывает метод "создать()", который возвращает полностью построенный и настроенный объект игрового персонажа. <br> **Применимость** - Когда вы хотите избавиться от «телескопического конструктора». - Когда ваш код должен создавать разные представления какого-то объекта. Например, деревянные и железобетонные дома. ### Прототип Также известен как: Клон, Prototype Позволяет копировать экземпляры, не вдаваясь в подробности их реализации. Паттерн Прототип поручает создание копий самим копируемым экземплярам. Он вводит общий интерфейс для всех экземпляров, поддерживающих клонирование. Это позволяет копировать экземпляры, не привязываясь к их конкретным классам. Обычно такой интерфейс имеет всего один метод clone. [ссылка](https://refactoring.guru/ru/design-patterns/prototype) ### Одиночка Также известен как: Singleton Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа. Все реализации одиночки сводятся к тому, чтобы скрыть конструктор по умолчанию и создать публичный статический метод, который и будет контролировать жизненный цикл экземпляра-одиночки. <br> [ссылка](https://refactoring.guru/ru/design-patterns/singleton)