1. Singleton
Одинак (Singleton) — породжувальний шаблон проєктування, який гарантує, що в однопоточному застосунку буде єдиний екземпляр певного класу, і надає глобальну точку доступу до цього екземпляра.

Дуже часто програмісти-початківці люблять зібрати утилітні методи в певний статичний клас – клас, що містить лише статичні методи. Такий підхід має низку мінусів – наприклад, не можна передати посилання на об'єкт цього класу, а методи важко тестувати тощо.
Як альтернативу запропонували рішення – клас-сінглтон: клас, який може мати лише один об'єкт. Цей об'єкт створюється лише в тому випадку, якщо він ще не існує, інакше повертається посилання на існуючий екземпляр.
Істотно те, що можна користуватися саме екземпляром класу, тому що при цьому в багатьох випадках стає доступнішою широка функціональність. Наприклад, цей клас може реалізовувати деякі інтерфейси та його об'єкт можна передати до інших методів, як імплементацію інтерфейсу. Що не можна зробити із набором статичних методів.
Плюси:
- Методи прив'язані до об'єкта, а не до статичного класу – можна передавати об'єкт за посиланням.
- Методи об'єкта значно легше тестувати та мокувати.
- Об'єкт створюється лише за потребою: відкладена ініціалізація об'єкта.
- Прискорення початкового запуску програми, якщо є безліч одиниць, які не потрібні для запуску.
- Одинака можна в подальшому перетворити на шаблон Стратегія або кілька таких об'єктів.
Мінуси:
- Ускладнюється контроль над міжпотоковими гонками та затримками.
- Багатопотокового "одинака" складно писати "з голови": доступ до давно побудованого одинака в ідеалі не повинен відкривати м'ютекс. Краще перевірені рішення.
- Конфлікт двох потоків через недобудованого одинака призведе до затримки.
- Якщо об'єкт створюється довго, затримка може заважати користувачеві або порушувати час. У разі його створення краще перенести на стадію ініціалізації програми.
- Потрібні особливі функції для модульного тестування - наприклад, щоб перевести бібліотеку в "не одинокий" режим і повністю ізолювати тести один від одного.
- Потрібна особлива тактика тестування готової програми, адже пропадає навіть поняття "найпростий процес запуску", адже запуск залежить від конфігурації.
2. Factory [Method]
Фабричний метод (Factory Method) — породжувальний шаблон проєктування, який надає підкласам (класам-спадкоємцям) інтерфейс для створення екземплярів певного класу. На момент створення спадкоємці можуть визначити, який клас створювати.
Іншими словами, цей патерн делегує створення об'єктів спадкоємцям батьківського класу. Це дозволяє використовувати у коді програми не конкретні класи, а маніпулювати абстрактними об'єктами на більш високому рівні.

Цей патерн визначає інтерфейс для створення об'єкта, але залишає підкласам рішення про те, на підставі якого класу створювати об'єкт. Фабричний метод дозволяє класу делегувати створення підкласів. Використовується, коли:
- класу заздалегідь невідомо, об'єкти яких підкласів йому потрібно створювати.
- клас спроєктовано так, щоб об'єкти, що він створює, специфікувалися підкласами.
- клас делегує свої обов'язки одному з кількох допоміжних підкласів, і планується визначити, який клас забере на себе ці обов'язки.
3. Abstract Factory
Абстрактна фабрика (Abstract factory) — породжувальний шаблон проєктування, який надає інтерфейс для створення сімейств взаємопов'язаних або взаємозалежних об'єктів без зазначення їх конкретних класів.
Шаблон реалізується створенням абстрактного класу Factory, який є інтерфейсом для створення компонентів системи (наприклад, для віконного інтерфейсу він може створювати вікна та кнопки). Потім пишуться класи, які реалізують цей інтерфейс.

Застосовується у випадках, коли програма має бути незалежною від процесу та типів створюваних нових об'єктів. Коли необхідно створити сімейства або групи взаємопов'язаних об'єктів, без можливості одночасного використання об'єктів із цих різних наборів в одному контексті.
Сильні сторони:
- ізолює конкретні класи;
- полегшує заміну сімейств продуктів;
- гарантує поєднання продуктів.
Припустимо, твоя програма працює з файловою системою. Тоді для роботи в Linux тобі потрібні об'єкти LinuxFile, LinuxDirectory, LinuxFileSystem. А для роботи у Windows тобі потрібні класи WindowsFile, WindowsDirectory, WindowsFileSystem.
Клас Path, який створюється через Path.of(), – це саме той випадок. Path — це насправді не клас, а інтерфейс, і він має реалізації WindowsPath та LinuxPath. А який саме об'єкт буде створено, приховано від твого коду і вирішуватиметься під час роботи програми.
4. Prototype
Прототип (Prototype) – породжувальний шаблон проєктування.
Цей патерн встановлює види об'єктів, що створюються, за допомогою екземпляра-прототипу та створює нові об'єкти через копіювання цього прототипу. Він дозволяє уникнути реалізації і дотримуватися принципу “програмування через інтерфейси”.
Як тип, що повертається, вказується інтерфейс/абстрактний клас на вершині ієрархії, а класи-спадкоємці можуть підставити туди спадкоємця, який реалізує цей тип. Простіше кажучи, це патерн створення об'єкта через клонування іншого об'єкта замість створення через конструктор.

Паттерн використовуєтьсяЮ щоб:
- уникнути додаткових зусиль щодо створення об'єкта стандартним шляхом (мається на увазі використання конструктора, тому що в цьому випадку також викличуться конструктори всієї ієрархії предків об'єкта), коли це занадто дорого для застосунку.
- уникнути успадкування творця об'єкта (object creator) у клієнтському застосунку, як це робить паттерн Abstract factory.
Використовуй цей шаблон проєктування, коли твоїй програмі байдуже, як саме в ній створюються, компонуються та видаються продукти:
- класи, що інстанціюються, визначаються під час виконання, наприклад, за допомогою динамічного завантаження;
- ти хочеш уникнути побудови ієрархій класів чи фабрик, паралельних до ієрархії класів продуктів;
- екземпляри класу можуть бути в одному з кількох різних станів. Може бути зручно встановити відповідну кількість прототипів і клонувати їх, а не інстанціювати щоразу клас вручну у відповідному стані.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ