Какие паттерны проектирования знаешь
Паттерны проектирования (design patterns) — это универсальные, повторяемые решения типичных проблем, возникающих при проектировании архитектуры программного обеспечения. Они не являются готовым кодом, а представляют собой концепции, которые можно адаптировать под конкретную задачу. Наиболее известной классификацией паттернов является классификация, предложенная "Бандой четырёх" (Gang of Four, GoF): Эрих Гамма, Ричард Хелм, Ральф Джонсон и Джон Влиссидес. Они разделили паттерны на три основные категории:
1. Порождающие паттерны (Creational Patterns)
Эти паттерны связаны с созданием объектов, позволяя системе быть независимой от конкретных классов создаваемых объектов.
1.1. Singleton (Одиночка)
Обеспечивает наличие только одного экземпляра класса и предоставляет к нему глобальную точку доступа.
-
Используется, например, для логгера, подключения к БД, конфигурации.
-
Пример: Database.getInstance().
1.2. Factory Method (Фабричный метод)
Определяет интерфейс для создания объекта, но позволяет подклассам решать, какой класс инстанцировать.
-
Позволяет использовать полиморфизм при создании объектов.
-
Пример: ShapeFactory.createShape("circle").
1.3. Abstract Factory (Абстрактная фабрика)
Позволяет создавать семейства взаимосвязанных объектов, не привязываясь к конкретным классам.
- Например, создание GUI-компонентов для разных ОС.
1.4. Builder (Строитель)
Отделяет создание сложного объекта от его представления, позволяя использовать один и тот же процесс построения для различных представлений.
- Пример: построение HTML-документа или сложного объекта с множеством опций.
1.5. Prototype (Прототип)
Создание нового объекта путем клонирования уже существующего.
- Используется для копирования сложных объектов.
2. Структурные паттерны (Structural Patterns)
Эти паттерны упрощают реализацию сложных структур и отношений между объектами.
2.1. Adapter (Адаптер)
Позволяет использовать несовместимые интерфейсы вместе. Преобразует интерфейс одного класса в интерфейс, ожидаемый клиентом.
- Пример: USB-переходник.
2.2. Bridge (Мост)
Отделяет абстракцию от её реализации, позволяя изменять их независимо.
- Полезен для работы с платформозависимыми реализациями.
2.3. Composite (Компоновщик)
Позволяет объединить объекты в древовидную структуру для представления иерархий.
- Пример: дерево компонентов GUI.
2.4. Decorator (Декоратор)
Добавляет объекту новые обязанности динамически.
- Пример: обёртка для логгирования метода или добавления функциональности.
2.5. Facade (Фасад)
Предоставляет унифицированный интерфейс к набору интерфейсов в подсистеме.
- Упрощает доступ к сложной системе.
2.6. Flyweight (Приспособленец)
Позволяет эффективно использовать память за счёт повторного использования объектов.
- Пример: символы в текстовом редакторе.
2.7. Proxy (Заместитель)
Представляет объект-заместитель, который контролирует доступ к другому объекту.
- Пример: защита, кэширование, удалённый доступ.
3. Поведенческие паттерны (Behavioral Patterns)
Они определяют алгоритмы и способы взаимодействия между объектами.
3.1. Chain of Responsibility (Цепочка обязанностей)
Передаёт запрос по цепочке обработчиков, пока кто-то не обработает его.
- Пример: обработка событий в UI.
3.2. Command (Команда)
Инкапсулирует запрос как объект, позволяя параметризовать клиентов с различными запросами.
- Удобно для реализации undo/redo.
3.3. Interpreter (Интерпретатор)
Задаёт грамматику языка и интерпретатор предложений этого языка.
- Пример: регулярные выражения.
3.4. Iterator (Итератор)
Предоставляет способ последовательного доступа ко всем элементам коллекции, не раскрывая её внутреннюю структуру.
- Пример: for...of в JavaScript или foreach в Java.
3.5. Mediator (Посредник)
Инкапсулирует взаимодействие между объектами, устраняя необходимость ссылаться друг на друга напрямую.
- Пример: диспетчер сообщений в UI.
3.6. Memento (Хранитель)
Сохраняет внутреннее состояние объекта без нарушения инкапсуляции.
- Пример: реализация откатов (undo).
3.7. Observer (Наблюдатель)
Определяет зависимость "один ко многим" между объектами, так что при изменении одного все зависят обновляются автоматически.
- Пример: подписка на события, реактивные библиотеки.
3.8. State (Состояние)
Позволяет объекту изменять поведение при изменении его внутреннего состояния.
- Пример: автомат с напитками.
3.9. Strategy (Стратегия)
Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми.
- Пример: выбор алгоритма сортировки.
3.10. Template Method (Шаблонный метод)
Определяет основу алгоритма в методе, оставляя реализацию некоторых шагов подклассам.
- Пример: шаги обработки данных, где часть шагов общие.
3.11. Visitor (Посетитель)
Позволяет добавить операцию к объекту без изменения самого объекта.
- Используется в компиляторах, парсерах AST.
Другие паттерны, вне GoF
-
MVC (Model-View-Controller) — разделение данных, логики и представления.
-
MVVM (Model-View-ViewModel) — популярен в SwiftUI, Android, WPF.
-
Singleton Scope — особенно актуален в Spring и DI-контейнерах.
-
Dependency Injection (DI) — внедрение зависимостей через конструкторы или свойства.
-
Service Locator — глобальный реестр зависимостей (менее предпочтителен).
-
Repository, Unit of Work — используются в архитектуре доступа к данным.
Эти паттерны формируют основу для архитектурных решений в разработке, особенно в масштабных и поддерживаемых проектах. Их знание важно для понимания чужого кода, совместной работы в команде и грамотного проектирования программных систем.