Создание синглтона класса без использования статического метода - PullRequest
9 голосов
/ 22 декабря 2011

Мне нужно создать синглтон-класс без сохранения статического метода.

Как я могу это сделать?

Ответы [ 7 ]

21 голосов
/ 22 декабря 2011

Создание перечисления с одним экземпляром

enum Singleton {
    INSTANCE;

    private Field field = VALUE;
    public Value method(Arg arg) { /* some code */ }
}

// You can use
Value v = Singleton.INSTANCE.method(arg);

РЕДАКТИРОВАТЬ: Учебник по перечислению Java показывает, как добавить поля и методы в перечисление.


Кстати: часто, когда вы можете использовать Singleton, он вам на самом деле не нужен, поскольку служебный класс будет делать то же самое.Еще более короткая версия - просто

enum Utility {;
    private static Field field = VALUE;
    public static Value method(Arg arg) { /* some code */ }
}

// You can use
Value v = Utility.method(arg);

. Где Singletons полезны, когда они реализуют интерфейс.Это особенно полезно для тестирования при использовании инъекции зависимости.(Один из недостатков использования замещения Singleton или служебного класса в модульных тестах)

например

interface TimeService {
    public long currentTimeMS();
}

// used when running the program in production.
enum VanillaTimeService implements TimeService {
    INSTANCE;
    public long currentTimeMS() { return System.currentTimeMS(); }
}

// used in testing.
class FixedTimeService implements TimeService {
    private long currentTimeMS = 0;
    public void currentTimeMS(long currentTimeMS) { this.currentTimeMS = currentTimeMS; }
    public long currentTimeMS() { return currentTimeMS; }
}

Как вы можете видеть, если ваш код везде использует TimeService, вы можете внедрить либоVanillaTimeService.INSTANCE или new FixedTimeService(), где вы можете контролировать время извне, т. Е. Ваши отметки времени будут одинаковыми при каждом запуске теста.

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

8 голосов
/ 22 декабря 2011
public class Singleton {
    public static final Singleton instance = new Singleton();
    private Singleton() {}
    public void foo() {}
}

затем используйте

Singleton.instance.foo();
2 голосов
/ 22 декабря 2011

Другим подходом является идиома одиночного держателя , которая предлагает инициализацию по требованию:

public class Something {
        private Something() {
        }

        private static class LazyHolder {
                public static final Something INSTANCE = new Something();
        }

        public Something getInstance() {
                return LazyHolder.INSTANCE;
        }
}

(пример изменен, метод getInstance сделан не статичным)

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

1 голос
/ 22 декабря 2011

Вы можете использовать один из контейнеров IoC (например, Google Guice ) и использовать свой класс как синглтон (нетерпеливый или ленивый - это зависит от ваших потребностей). Это просто и гибко, поскольку создание экземпляров контролируется платформой IoC - вам не нужны никакие изменения кода, если, например, вы решите сделать свой класс не одиночным позже.

1 голос
/ 22 декабря 2011

Следуйте рецепту перечисления Джошуа Блоха во 2-й редакции «Эффективной Явы».Это лучший способ создать синглтон.

Я не понимаю, почему так много всего получается.Разве синглтон не дискредитированный шаблон дизайна?GoF проголосовал бы сегодня за остров.

0 голосов
/ 22 декабря 2011

Из конструктора вам нужно выполнить chceck, если где-то уже есть экземпляр класса. Таким образом, вам нужно хранить ссылку на ваш экземпляр singleton в статической переменной или классе. Тогда в конструкторе singleton я всегда проверял, существует ли экземпляр класса singleton. Если да, я ничего не буду делать, если нет, я создам это и установлю ссылку.

0 голосов
/ 22 декабря 2011

Используйте фабрику объектов, извлеките объект-одиночка с этой фабрики.

ObjectFactory factory;
....
MySingletonObject obj = factory.getInstance(MySingletonObject.class);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...