Я читаю о шаблоне проектирования Singleton и оцениваю различные реализации. У меня есть сомнения, с ниже реализациях:Singleton со статическим внутренним классом и двойной проверкой блокировки
А. Singleton Реализация со статическим внутренним классом
public class SingletonWithStaticClass {
private SingletonWithStaticClass(){}
private static class SingletonInnerClass{
public static SingletonWithStaticClass INSTANCE = new SingletonWithStaticClass();
}
public static SingletonWithStaticClass getInstance(){
return SingletonInnerClass.INSTANCE;
}
}
B. Singleton двойной проверенного запирающего
public class SingletonWithDoubleCheck {
private static SingletonWithDoubleCheck INSTANCE = null;
private SingletonWithDoubleCheck(){
if(INSTANCE != null){
throw new RuntimeException("Accessing private constructor is prohibited. Use getInstance method instead");
}
}
public static SingletonWithDoubleCheck getInstance(){
if(INSTANCE == null){
synchronized (SingletonWithDoubleCheck.class) {
if(INSTANCE == null){
INSTANCE = new SingletonWithDoubleCheck();
}
}
}
return INSTANCE;
}
}
Какой из них лучше?
Я чувствую, что мы можем получить доступ к частному конструктору с отражением в первой реализации, где вторая реализация является безопасной (от рефлексивной атаки).
Однако, я не собираюсь использовать любого из них в моем рабочем коде, я буду использовать перечисления вместо этого. Но из этих двух, не первая реализация нарушена, когда рассматривается атака отражения?
Пожалуйста, исправьте меня, если мое понимание неверно.
Модель одиночного дизайна не предназначена, в общем, противостоять какой-то преднамеренной «атаке». Если кто-то использует рефлексию для раскрытия частного конструктора, то их ответственность заключается в том, чтобы знать, что то, что они делают, противоречит предполагаемому использованию кода. – khelwood
Второй небезопасный, как указано. Это было хэшировано и перефразировано. Я полностью согласен с хелвудом. Синглтон - это дизайн (анти). Не инструмент безопасности. Если у кого-то есть доступ к вашему коду, он может делать все, используя рефлексию. –
@JBNizet AFAIK был исправлен в Java 5.0, если вы использовали поле 'volatile', но оно показывает, что оно подвержено ошибкам. –