Запрос для комментариев: паттерн Singleton, реализованный на Java


У меня есть несколько служебных классов, которые должны только когда-либо один экземпляр в памяти, такие как LogHelper, CacheHelper и т. д. Один экземпляр, чтобы управлять ими всеми.

Я никогда не реализован синглтон в Java, так что я хотел разместить свой первый перевал и посмотреть, если кто-то имел серьезные проблемы с этим, или просто полезная критика. Я хочу убедиться, что моя конструкция будет иметь нужный характер, когда я иду, чтобы использовать эти Singleton-классы на протяжении всей моей кода.

Синглтон:

public class Singleton
{
    private static Singleton instance;

    protected Singleton()
    {
        super();
    }

    public static synchronized Singleton getInstance()
    {
        if(instance == null)
            instance = instantiate();

        return instance;
    }

    // Wanted to make this abstract and let subclasses @Override it,
    // but combining 'abstract' and 'static' is illegal; makes sense!
    protected static Singleton instantiate()
    {
        return new Singleton();
    }
}

LogHelper (одноэлементный, так как все мои классы будут использовать его, чтобы писать сообщения в той же окрестности):

public class LogHelper extends Singleton
{
    protected static LogHelper instantiate()
    {
        return new LogHelper(...blah...);
    }

    public LogHelper(...blah...)
    {
        // Initialize the singleton LogHelper
    }

    // More methods for logging, etc.
}

Вот как я хочу использовать его на протяжении всей моей кода:

LogHelper logHelper = LogHelper.getInstance();
logHelper.logInfo("...");

Что меня беспокоит , это то, что я, возможно, уточки это неправильно и идет по неверному авеню. Кто-нибудь может взвесить на мой дизайн?!?

Спасибо!



878
4
задан 6 августа 2011 в 02:08 Источник Поделиться
Комментарии
5 ответов

К сожалению, нет никакого способа (которые я знаю), чтобы предотвратить подкласс от предоставления общедоступного конструктора - как результат, создание Одноэлементного базового класса не может быть в ваших интересах. Если ваша цель-реализовать Синглтон-Несс, это, вероятно, лучше всего реализовать что-то вроде следующего класса-по класса основе:

public class SomeSingletonClass {
public static final SomeSingletonClass INSTANCE = new SomeSingletonClass();

private SomeSingletonClass(){
}

// ...
}

Многие IDE (например, IntelliJ) будет создавать котел-плита Синглтон код для вас с нажатием кнопки.

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

Я также заметил, что у тебя ленивый/синхронизированное инициализатора ваш пример - это, наверное, не стоит в большинстве случаев.

5
ответ дан 6 августа 2011 в 02:08 Источник Поделиться

Самый лучший шаблон для синглтона, который гарантированно будет потокобезопасным и минимизирует замок над головой (потому что его нет) это:

public class Singleton {
private Singleton() {}

private static class InstanceHolder {
static Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
return InstanceHolder.INSTANCE;
}
}

Это ленивой инициализации , но не несет никакой замок над головой. Это гарантированно безопасными модель памяти Java: внутренний статический класс не загружается до тех пор, пока первый вызов getIinstance() и все статические initializtion гарантированно будет завершена до класса используется, поэтому экземпляр полностью создан при первом обращении к ним.

Примечание: проверил замок узора нарушается - см. В этой статье , которая объясняет точно, почему.

8
ответ дан 6 августа 2011 в 06:08 Источник Поделиться

Самый простой Синглтон, начиная с Java 5.0 (2004), чтобы использовать перечислимый.

public enum SomeSingletonClass {
INSTANCE;
}

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

Однако в вашем случае, необходимо только служебный класс.

enum Log {;
public static void info(String text) { }
}

Log.info("...");

7
ответ дан 6 августа 2011 в 12:08 Источник Поделиться

"Оригинал" одноэлементный шаблон проектирования опирался на класс, не подвергая публичных конструкторов так, чтобы он мог контролировать реализацию себя, инкапсулируя все случаи использования нового класса:

public class SomeSingletonClass
{
private static SomeSingletonClass instance;

//disallow other classes from instantiating new instances
private SingletonClass()
{
}

public synchronized SomeSingletonClass getInstance()
{
if(instance == null)
instance = new SomeSingletonClass(); // instantiate here
return instance;
}
}

Путем создания подклассов синглтон, вы бы позволить подклассам создать несколько экземпляров синглтона, там потерять синглтон собственность на родителей. Так, следующая строка, вероятно, результат в нескольких экземплярах Синглтон создается в вашем случае:

public LogHelper(...blah...)
{
// Initialize the singleton LogHelper
}

Но это гораздо хуже, чем можно предсказать. Если клиент LogHelper ссылается на следующее:

LogHelper logHelper = new LogHelper(...blah...);
LogHelper anotherHelper = new LogHelper(...blah...);

у вас будет два LogHelper случаи, что виновником является публичной видимости LogHelper конструктор. Так что ваш подкласс не одноэлементного вообще.

Если вы хотите реализовать паттерн Singleton в нескольких классах, то лучше не рассматривать его как свойство не может быть унаследовано. Скорее, вы должны воссоздать поведение в каждом отдельном классе.

1
ответ дан 6 августа 2011 в 02:08 Источник Поделиться

я всегда считал, что это синглтон код надежный . синхронизировать на 'замок' объект создавать синглтон потокобезопасным

public class Singleton{

private static final Object LOCK = new Object();
private static Singleton singleton;

private Singleton(){}
/**
* Returns the singleton instance of <CODE>Singleton
создавая его, если
* необходимые.
*


*
* @возвращает одноэлементный экземпляр Singloton
*/
публичный статический Синглтон деыпзьапсе() {

// Синхронизации на замок, чтобы убедиться, что мы не в конечном итоге создание
// двух синглтонов.
синхронизации (блокировки) {
если (нуль == синглтон) {

синглтон = новый Синглтон();

}
}

возвращение синглтон;
}
}

1
ответ дан 6 августа 2011 в 04:08 Источник Поделиться