2009-09-30 4 views

ответ

6

Возможно, лучший способ - использовать перечисление с одним экземпляром. Это имеет дополнительное преимущество - быть сериализуемым и гарантировать односторонность в отношении сериализации и отражения, чего нет в «простой» реализации Singleton (частный? У меня есть отражение, я издеваюсь над вашими модификаторами доступа!). Это также очень прост в реализации:

public enum Singleton { 
    INSTANCE; 

    // fields and methods go here 
} 
+0

+1 за издевательство над модификаторами доступа. Я lol'd. :) – corsiKa

0

Одиночные игры не являются потоковыми по умолчанию. Обычный способ создания синглета - иметь фабричный метод, который обрабатывает создание одного экземпляра. Таким образом вы можете управлять созданием экземпляра.

2
public class Singleton { 
    public static final Singleton INSTANCE = new Singleton(); 
    private Singleton() { ... } 
} 

Использование переменной статического экземпляра предпочтительнее внутреннего класса «Держатель». Если вам нравится, вы также можете сделать статический член частным и предоставить метод для его доступа, но все, что делает, это добавить еще один вызов метода в стек.

+0

Это скорее зависит от того, что вы пытаетесь достичь, как к тому, что является предпочтительным - держатель дает вам ленивый синглтон, тем проще версия не дает вам отложенной загрузки. –

+0

Да, это так. Java не загружает классы до их первого использования. –

+1

Не совсем верно. Он загружает их, когда они сначала ссылаются, например. в сигнатуре метода другого класса. – skaffman

1

Что касается ленивого запуска: getInstance() возвращает одиночный элемент или создает его, если это первый вызов.

public class MySingleton 
{ 
    private static MySingleton instance; 

    private MySingleton() 
    { 
     // construct object . . . 
    } 

    // For lazy initialization 
    public static synchronized MySingleton getInstance() 
    { 
     if (instance==null) 
     { 
      instance = new MySingleton(); 
     } 
     return instance; 
    } 

    // Remainder of class definition . . . 
} 
+1

Леновый экземпляр почти никогда не нужен, и если это так, Java загружает классы лениво, поэтому создание экземпляра в декларации фактически * является ленивой инстанцией - без накладных расходов на синхронизацию (в очень редких случаях это не достаточно лениво, а ответ скаффмана лучше) , –

+0

Также обратите внимание, что эта реализация синхронизирует каждую попытку получения ссылки на экземпляр. Поскольку большинство кода будет делать что-то вроде: Singleton.getInstance.doSomething(); Singleton.getInstance.doSomethingElse(); Общий эффект будет дополнительной синхронизацией, строго ограничивающей параллелизм без гарантий безопасности потоков в терминах доступа/мутации члена. –

+0

Двойная проверка блокировки в Java нарушена http://www.javaworld.com/jw-02-2001/jw-0209-double.html Короче говоря, этот способ гарантировать, что этот класс создается только один раз, может привести к трудно найти проблемы параллелизма. Никогда не используйте это. – Buhb

11

Лучший способ сделать синглтон? Используйте перечисление.

public enum Singleton { 
    INSTANCE; 
    public void foo(){ ... } 
} 

// Usage: 
Singleton.INSTANCE.foo(); 

Вы получаете много помощи от VM не только избежать двойного экземпляра, но это также поможет вам избежать десериализаций коррупции.

0

Если вы беспокоитесь о параллелизме, вы не будете использовать общее глобальное состояние.

+2

Если синглтон содержит накопление результатов от сингулярной распараллеливаемой задачи, почему бы и нет? Синглтон олицетворяет глобальное состояние, и поэтому он будет справедливым сценарием использования. –

+1

Существует несколько вариантов использования для классов, представленных только с одним экземпляром, который разделяется между процессами.Типичный хорошо продуманный webapp с использованием пружины, вероятно, будет иметь кучу классов, созданных в одноэлементном пространстве, разделяемых между рабочими потоками. – Buhb

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