Сравните паттерны проектирования Singleton, Factory, Observer и Strategy: опишите пример использования для каждого, плюсы, минусы и какие антипаттерны с ними связаны
Singleton - Что: гарантирует единственный экземпляр класса и глобальную точку доступа к нему. - Пример использования: менеджер конфигурации или логгер, к которому нужно единообразно обращаться из разных модулей. - Плюсы: - Простая реализация глобального состояния/ресурса. - Удобно, когда действительно нужен один экземпляр (например, единственная сессия). - Может откладывать создание до первого запроса (lazy init). - Минусы: - Скрытые зависимости, ухудшение тестируемости (мокирование сложнее). - Склеивает жизненные циклы объектов, затрудняет параллелизм и инициализацию. - Часто приводит к глобальному состоянию и связанности модулей. - Неправильная реализация в многопоточности — гонки/дубль-экземпляры. - Связанные антипаттерны: - Global state / God object — Singleton используется вместо явной зависимости. - Singleton-as-namespace / Static class — превращение в набор статических методов. Factory (Simple/Factory Method/Abstract Factory) - Что: инкапсулирует создание объектов, позволяя менять конкретные классы без изменения кода клиента. - Пример использования: фабрика для создания DAO/репозиториев в зависимости от конфигурации (SQL/NoSQL), GUI-виджеты для разных платформ. - Плюсы: - Изоляция логики создания, упрощает замену реализаций. - Поддержка Open/Closed: добавление новых типов без изменения клиентов. - Снижает дублирование кода создания. - Минусы: - Увеличение числа классов/слоя абстракции. - Сложность, если фабрика становится «жирной» и содержит много условной логики. - Иногда преждевременная абстракция (overengineering). - Связанные антипаттерны: - Factory hell / God factory — одна фабрика отвечает за слишком много типов. - Switch/if-else factory — фабрика реализована через большие условные операторы вместо полиморфизма. Observer (Publisher/Subscriber) - Что: объект (издатель) уведомляет зарегистрированных наблюдателей об изменениях состояния. - Пример использования: модель-вид-контроллер (MVC) — модель пушит обновления в виды; событийная система/шина сообщений внутри приложения. - Плюсы: - Слабая связность между компонентами (издатель не знает деталей наблюдателей). - Удобно для реактивного обновления и событийных архитектур. - Масштабируемость подписок (несколько слушателей). - Минусы: - Управление жизненным циклом подписчиков (утечки памяти, если не отписываться). - Неявный поток управления — сложнее отлаживать последовательность событий. - Возможность циклических уведомлений и «штормов событий». - Требует политики обработки ошибок/приоритизации уведомлений. - Связанные антипаттерны: - Event soup / Spaghetti events — хаотичная сеть подписок, трудно понять кто и когда реагирует. - Memory leak via listeners — забытые отписки в GUI/мобильных приложениях. Strategy - Что: определяет семейство алгоритмов, инкапсулирует каждый и делает их взаимозаменяемыми. - Пример использования: разные алгоритмы сортировки/компрессии/авторизации выбираются в рантайме; ценообразование — разные стратегии расчёта скидок. - Плюсы: - Замена поведения без изменения клиента (открытость для расширения). - Упрощает тестирование алгоритмов отдельно. - Убирает условные операторы, делегируя разветвления в классы стратегий. - Минусы: - Увеличение числа классов (много мелких стратегий). - Передача контекста/данных между клиентом и стратегией может быть громоздкой. - Иногда стратегия используется, где проще использовать параметризированную функцию — избыточность. - Связанные антипаттерны: - Switch-based strategy (замена полиморфизма большим if/else) — не использован паттерн, остаётся условная логика. - Speculative generality — введение стратегий заранее «на всякий случай», когда одна реализация достаточна. Краткое сравнение (одно предложение) - Singleton даёт глобальную точку доступа (риски тестируемости), Factory управляет созданием (склонность к большому числу фабрик), Observer решает задачи подписки/уведомления (риск событийной спагетти и утечек), Strategy инкапсулирует семейства алгоритмов (риск избыточной абстракции).
- Что: гарантирует единственный экземпляр класса и глобальную точку доступа к нему.
- Пример использования: менеджер конфигурации или логгер, к которому нужно единообразно обращаться из разных модулей.
- Плюсы:
- Простая реализация глобального состояния/ресурса.
- Удобно, когда действительно нужен один экземпляр (например, единственная сессия).
- Может откладывать создание до первого запроса (lazy init).
- Минусы:
- Скрытые зависимости, ухудшение тестируемости (мокирование сложнее).
- Склеивает жизненные циклы объектов, затрудняет параллелизм и инициализацию.
- Часто приводит к глобальному состоянию и связанности модулей.
- Неправильная реализация в многопоточности — гонки/дубль-экземпляры.
- Связанные антипаттерны:
- Global state / God object — Singleton используется вместо явной зависимости.
- Singleton-as-namespace / Static class — превращение в набор статических методов.
Factory (Simple/Factory Method/Abstract Factory)
- Что: инкапсулирует создание объектов, позволяя менять конкретные классы без изменения кода клиента.
- Пример использования: фабрика для создания DAO/репозиториев в зависимости от конфигурации (SQL/NoSQL), GUI-виджеты для разных платформ.
- Плюсы:
- Изоляция логики создания, упрощает замену реализаций.
- Поддержка Open/Closed: добавление новых типов без изменения клиентов.
- Снижает дублирование кода создания.
- Минусы:
- Увеличение числа классов/слоя абстракции.
- Сложность, если фабрика становится «жирной» и содержит много условной логики.
- Иногда преждевременная абстракция (overengineering).
- Связанные антипаттерны:
- Factory hell / God factory — одна фабрика отвечает за слишком много типов.
- Switch/if-else factory — фабрика реализована через большие условные операторы вместо полиморфизма.
Observer (Publisher/Subscriber)
- Что: объект (издатель) уведомляет зарегистрированных наблюдателей об изменениях состояния.
- Пример использования: модель-вид-контроллер (MVC) — модель пушит обновления в виды; событийная система/шина сообщений внутри приложения.
- Плюсы:
- Слабая связность между компонентами (издатель не знает деталей наблюдателей).
- Удобно для реактивного обновления и событийных архитектур.
- Масштабируемость подписок (несколько слушателей).
- Минусы:
- Управление жизненным циклом подписчиков (утечки памяти, если не отписываться).
- Неявный поток управления — сложнее отлаживать последовательность событий.
- Возможность циклических уведомлений и «штормов событий».
- Требует политики обработки ошибок/приоритизации уведомлений.
- Связанные антипаттерны:
- Event soup / Spaghetti events — хаотичная сеть подписок, трудно понять кто и когда реагирует.
- Memory leak via listeners — забытые отписки в GUI/мобильных приложениях.
Strategy
- Что: определяет семейство алгоритмов, инкапсулирует каждый и делает их взаимозаменяемыми.
- Пример использования: разные алгоритмы сортировки/компрессии/авторизации выбираются в рантайме; ценообразование — разные стратегии расчёта скидок.
- Плюсы:
- Замена поведения без изменения клиента (открытость для расширения).
- Упрощает тестирование алгоритмов отдельно.
- Убирает условные операторы, делегируя разветвления в классы стратегий.
- Минусы:
- Увеличение числа классов (много мелких стратегий).
- Передача контекста/данных между клиентом и стратегией может быть громоздкой.
- Иногда стратегия используется, где проще использовать параметризированную функцию — избыточность.
- Связанные антипаттерны:
- Switch-based strategy (замена полиморфизма большим if/else) — не использован паттерн, остаётся условная логика.
- Speculative generality — введение стратегий заранее «на всякий случай», когда одна реализация достаточна.
Краткое сравнение (одно предложение)
- Singleton даёт глобальную точку доступа (риски тестируемости), Factory управляет созданием (склонность к большому числу фабрик), Observer решает задачи подписки/уведомления (риск событийной спагетти и утечек), Strategy инкапсулирует семейства алгоритмов (риск избыточной абстракции).