В каких сценариях применяется паттерн Singleton?

«В каких сценариях применяется паттерн Singleton?» — вопрос из категории Паттерны, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Singleton гарантирует, что у класса существует только один экземпляр, и предоставляет глобальную точку доступа к нему.

Типичные сценарии применения:

  1. Управление общими ресурсами:

    • Конфигурация приложения: Единый источник глобальных настроек.
    • Логгер: Централизованная запись логов.
    • Кеш в памяти: Глобальное хранилище часто используемых данных.
    • Пул соединений с БД: Управление ограниченным ресурсом подключений.
  2. Доступ к системным сервисам: Например, объект, представляющий окно консоли или менеджер драйверов.

Пример потокобезопасной реализации (через статическое поле):

public class AppConfig {
    // Экземпляр создаётся при загрузке класса (потокобезопасно)
    private static final AppConfig INSTANCE = new AppConfig();
    private Properties settings;

    private AppConfig() {
        // Приватный конструктор
        loadConfiguration();
    }

    public static AppConfig getInstance() {
        return INSTANCE;
    }

    public String getProperty(String key) {
        return settings.getProperty(key);
    }
}
// Использование:
String dbUrl = AppConfig.getInstance().getProperty("database.url");

Важные замечания:

  • Многопоточность: Простая реализация с ленивой инициализацией (if (instance == null)) не потокобезопасна. Используйте synchronized, статическую инициализацию или enum.
  • Тестирование: Singleton может усложнять модульное тестирование из-за глобального состояния. Часто предпочтительнее использовать Dependency Injection (DI) контейнеры (например, Spring), которые по умолчанию создают бины в скоупе singleton, но при этом обеспечивают гибкость и упрощают тестирование.