2015-12-29 3 views
4

Я читаю о шаблоне проектирования 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; 
} 

}

Какой из них лучше?

Я чувствую, что мы можем получить доступ к частному конструктору с отражением в первой реализации, где вторая реализация является безопасной (от рефлексивной атаки).

Однако, я не собираюсь использовать любого из них в моем рабочем коде, я буду использовать перечисления вместо этого. Но из этих двух, не первая реализация нарушена, когда рассматривается атака отражения?

Пожалуйста, исправьте меня, если мое понимание неверно.

+1

Модель одиночного дизайна не предназначена, в общем, противостоять какой-то преднамеренной «атаке». Если кто-то использует рефлексию для раскрытия частного конструктора, то их ответственность заключается в том, чтобы знать, что то, что они делают, противоречит предполагаемому использованию кода. – khelwood

+0

Второй небезопасный, как указано. Это было хэшировано и перефразировано. Я полностью согласен с хелвудом. Синглтон - это дизайн (анти). Не инструмент безопасности. Если у кого-то есть доступ к вашему коду, он может делать все, используя рефлексию. –

+0

@JBNizet AFAIK был исправлен в Java 5.0, если вы использовали поле 'volatile', но оно показывает, что оно подвержено ошибкам. –

ответ

6

Оба являются чрезмерно сложными. Первый был лучшим вариантом перед Java 5.0, однако второй никогда не был хорошим вариантом. Она не работает, прежде чем Java 5.0, она требует volatile поля и после этой версии вы можете использовать enum

Я предпочитаю использовать в enum определить класс только с одним экземпляром. Это класс final, потокобезопасный, ленивый загруженный и имеет конструктор private.

enum Singleon { 
    INSTANCE; 
} 

Двойной замок однотональный полезен, если вы должны предоставить информацию о конфигурации в его конструкции. В этом случае я предпочитаю использовать Dependency Injection для предоставления/конфигурирования синглетонов и наличия только синглтонов без гражданства, которые не требуют настройки.

1

Ничто не является хорошим - и попытка сравнить их с использованием разных шкал контрпродуктивна.

Первый излишне сложный и, как вы говорите, открыт для взлома отражения, но также и другой, чуть меньше.

Второй использует synchronized, который поставляется со стоимостью.

+2

Любой ленивый загруженный раствор нуждается в каком-то замке. Использование поля 'final' означает, что после того, как объект был инициализирован, нет никакой стоимости (даже проверки). –

Смежные вопросы