Ответ
Да, использовал. Singleton — это порождающий паттерн, гарантирующий существование только одного экземпляра класса и предоставляющий глобальную точку доступа к нему.
Типичные сценарии использования:
- Конфигурация приложения (глобальный объект настроек).
- Логгеры.
- Кэши.
- Подключения к базе данных или пулы соединений (с осторожностью).
Пример реализации на Java (ленивая инициализация):
public class Singleton {
private static volatile Singleton instance;
private Singleton() {} // Приватный конструктор
public static Singleton getInstance() {
if (instance == null) { // Первая проверка (без блокировки)
synchronized (Singleton.class) {
if (instance == null) { // Вторая проверка (под блокировкой)
instance = new Singleton();
}
}
}
return instance;
}
}
Ключевые аспекты и нюансы:
- Потокобезопасность: Базовая реализация не является потокобезопасной. Для этого используется Double-Checked Locking (как в примере выше) с полем
volatileили синхронизация всего методаgetInstance()(что менее эффективно). - Способы инициализации:
- Ленивая (Lazy): Экземпляр создается при первом вызове
getInstance(). - Жадная (Eager):
private static final Singleton INSTANCE = new Singleton();— экземпляр создается при загрузке класса.
- Ленивая (Lazy): Экземпляр создается при первом вызове
- Проблемы и нарушения: Паттерн может быть нарушен через:
- Рефлексию (можно вызвать приватный конструктор).
- Сериализацию/десериализацию (создастся новый объект).
- Клонирование.
- Рекомендуемая альтернатива (в Java): Использование enum, который по своей природе гарантирует единственный экземпляр и защищен от рефлексии и сериализации.
public enum EnumSingleton { INSTANCE; public void doSomething() { /* ... */ } } - Современные альтернативы: Внедрение зависимостей (DI) через фреймворки (Spring, Guice), где контейнер сам управляет жизненным циклом и единственностью бинов (
@Singleton/@Scope("singleton")).