11. Реализовать паттерн Singleton
Условие задачи:
Необходимо реализовать паттерн Singleton.
Класс должен:
иметь только один экземпляр в рамках ClassLoader;
запрещать создание объекта через
newизвне класса;предоставлять глобальную точку доступа к экземпляру;
быть потокобезопасным;
создавать экземпляр лениво — только при первом обращении.
Спойлеры к решению
Подсказки
private.💡 Для ленивой и потокобезопасной инициализации можно использовать Initialization-on-demand holder idiom.
💡 Вложенный статический класс загружается только при первом обращении к нему.
💡 Инициализация статических полей класса в Java выполняется потокобезопасно.
Решение
public final class Singleton {
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
Пример использования:
Singleton first = Singleton.getInstance();
Singleton second = Singleton.getInstance();
System.out.println(first == second); // true
Приватный конструктор:
private Singleton() {
}
не позволяет создать экземпляр обычным способом:
new Singleton();
Метод:
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
обращается к вложенному классу SingletonHolder.
Именно при первом обращении к нему создаётся экземпляр:
private static final Singleton INSTANCE = new Singleton();
Инициализация класса в JVM выполняется потокобезопасно, поэтому дополнительный synchronized здесь не требуется.
Свойства такого решения:
ленивая инициализация;
потокобезопасность;
отсутствие синхронизации при каждом вызове
getInstance();простая реализация.
Класс дополнительно объявлен final, чтобы его нельзя было расширить наследованием.
Альтернативный вариант Singleton в Java — enum:
public enum Singleton {
INSTANCE
}
Он особенно удобен, если не требуется именно реализация через обычный класс.