Ответ
Singleton гарантирует, что у класса существует только один экземпляр, и предоставляет глобальную точку доступа к нему.
Типичные сценарии применения:
-
Управление общими ресурсами:
- Конфигурация приложения: Единый источник глобальных настроек.
- Логгер: Централизованная запись логов.
- Кеш в памяти: Глобальное хранилище часто используемых данных.
- Пул соединений с БД: Управление ограниченным ресурсом подключений.
-
Доступ к системным сервисам: Например, объект, представляющий окно консоли или менеджер драйверов.
Пример потокобезопасной реализации (через статическое поле):
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, но при этом обеспечивают гибкость и упрощают тестирование.