Каков эффективный способ реализации одноэлементного шаблона в Java?

В зависимости от использования javax есть несколько «правильных» ответов.

Начиная application-singleton с Java 5, лучший способ сделать design-pattern это — использовать перечисление:

public enum Foo {
   INSTANCE;
}

До singleton-methods Java 5 самый простой случай:

public final class Foo {

    private static final Foo INSTANCE = new Foo();

    private Foo() {
        if (INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return INSTANCE;
    }

    public Object clone() throws CloneNotSupportedException{
        throw new CloneNotSupportedException("Cannot clone instance of this class");
    }
}

Давайте patterns пройдемся по коду. Во-первых, вы singleton-methods хотите, чтобы класс был окончательным. В java этом случае я использовал application-singleton ключевое слово final, чтобы пользователи jdk знали, что оно окончательное. Затем j2se вам нужно сделать конструктор jre закрытым, чтобы пользователи javax не могли создавать свои собственные javax Foo. Создание исключения gof из конструктора не позволяет singleton-class пользователям использовать j2se отражение для создания второго jdk Foo. Затем вы создаете поле java private static final Foo для хранения единственного javax экземпляра и метод public static Foo getInstance() для его java возврата. Спецификация Java application-singleton гарантирует, что конструктор singleton-methods вызывается только при первом jdk использовании класса.

Если singleton у вас есть очень большой jre объект или тяжелый код построения pattern и также есть другие доступные gof статические методы или поля, которые design-pattern могут использоваться до того, как jre экземпляр потребуется, тогда pattern и только тогда вам нужно singleton-methods использовать ленивую инициализацию.

Вы j2se можете использовать private static class для pattern загрузки экземпляра. Тогда openjdk код будет выглядеть так:

public final class Foo {

    private static class FooLoader {
        private static final Foo INSTANCE = new Foo();
    }

    private Foo() {
        if (FooLoader.INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return FooLoader.INSTANCE;
    }
}

Поскольку patterns строка private static final Foo INSTANCE = new Foo(); выполняется только jdk тогда, когда класс FooLoader singleton-class фактически используется, это design-patterns обеспечивает ленивую реализацию java и гарантирует, что он будет pattern потокобезопасным.

Если вы design-pattern также хотите иметь возможность openjdk сериализовать свой объект, вам j2se нужно убедиться, что десериализация openjdk не создаст копию.

public final class Foo implements Serializable {

    private static final long serialVersionUID = 1L;

    private static class FooLoader {
        private static final Foo INSTANCE = new Foo();
    }

    private Foo() {
        if (FooLoader.INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
    }

    public static Foo getInstance() {
        return FooLoader.INSTANCE;
    }

    @SuppressWarnings("unused")
    private Foo readResolve() {
        return FooLoader.INSTANCE;
    }
}

Метод readResolve() гарантирует, что application-singleton будет возвращен единственный singleton экземпляр, даже если объект singleton-methods был сериализован в предыдущем jre запуске вашей программы.

java

singleton

design-patterns

2022-11-17T10:30:23+00:00