В то время как я согласен с ответом Энди Тернера, чтобы избежать синглотонов, если это возможно, я добавлю это для полноты: статический синхронизированный метод getInstance является реликтом прошлого. Существует не менее 3 одноэлементных реализаций шаблонов, которые этого не требуют.
а) стремится одноточечно
public class EagerSingleton{
private EagerSingleton(){}
private static final EagerSingleton INSTANCE = new EagerSingleton();
public static EagerSingleton getInstance(){ return INSTANCE; }
}
Это инициализируется во время класса нагрузки, всякий раз, когда вы ссылаетесь на класс EagerSingleton каким-либо образом (например, объявив переменную этого типа).
б) ленивым одноточечно
public class LazySingleton{
private LazySingleton(){}
private static class Holder{
private static final LazySingleton INSTANCE = new LazySingleton();
}
public static LazySingleton getInstance(){ return Holder.INSTANCE; }
}
Это инициализируется во время вызова, первый раз при вызове метода GetInstance(). Теперь загрузчик классов загружает класс держателя и инициализирует поле INSTANCE, и это гарантированно синхронизируется. Используйте эту версию, если ваш синглтон имеет дорогостоящую настройку и не всегда необходим.
с) перечисление Singleton
public enum EnumSingleton{
INSTANCE;
// and if you want, you can add the method, too, but it's
// unnecessary:
public static EnumSingleton getInstance(){ return INSTANCE; }
}
Enum элементы времени компиляции константы, то есть их уникальность гарантируется во время компиляции, а не только во время выполнения (во время выполнения, одиночек являются уникальными для каждого загрузчика класса, и что применяется ко всем версиям). Это лучший способ пойти, если только ваши требования не распространяются на существующий класс.
версии перечисления дает много других возможностей бесплатно:
- равна реализации/хэш-код/ToString из коробки
- защиты от Десериализация атак
- многотонной поддержки (просто добавьте еще один перечисление)
Итак, в следующий раз, когда вы увидите, что кто-то напишет механизм блокировки с двойной проверкой или аналогичный, скажите им, что они слишком сложны и техничны и др. Пусть загрузчик классов выполнит вашу работу.
Со всеми 3 версиями: убедитесь, что функциональность, которую вы используете, поддерживается интерфейсом и кодом для этого интерфейса, а не типом реализации. Это сделает ваш код поддающимся проверке.
В идеале вы не использовали бы Singleton вообще. Когда я должен, я предпочитаю использовать 'enum', в этом случае я бы написал' MySingleton.INSTANCE.doSomething() ' –
Эти два примера идентичны, хотя @PeterLawrey имеет право рекомендовать перечисления для одиночных чисел. –
Определите «правильное» - что конкретно вы спрашиваете? Это идентично, но в первом примере вы получаете экземпляр и используете его позже. –