Является Одноэлементная Перечислимая Singleton Типа действительно широко принятой хорошей идеей?

Объект 3 из Эффективного Java Josh Block (Осуществляют Свойство Singleton С Частным конструктором или Перечислителем) упоминают, что, "В то время как этот подход должен все же быть широко принят, одноэлементный перечислимый тип является лучшим способом реализовать одиночный элемент".

Пример:

   public enum Elvis {
       INSTANCE;
       private final String[] favoriteSongs =
           { "Hound Dog", "Heartbreak Hotel" };
       public void printFavorites() {
           System.out.println(Arrays.toString(favoriteSongs));
       }
   }

Продолженный: "Этот подход функционально эквивалентен общедоступному полевому подходу, за исключением того, что это более кратко, обеспечивает оборудование для сериализации бесплатно и обеспечивает бронированную гарантию от нескольких инстанцирование, даже перед лицом сложной сериализации или отражательных нападений".

Самое большое отрицание, которое я вижу: разве перечисления, как не предполагается, не имеют изменяемое состояние? Кажется распространенным использовать Singleton с состоянием.

Также - этот шаблон на самом деле распространен больше начиная с года издания (2-й Выпуск опубликовал 2008)?

20
задан Tom Tresansky 23 June 2010 в 16:58
поделиться

5 ответов

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

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

Что касается популярности этого паттерна проектирования, то я встречал его довольно часто, но не настолько, чтобы сказать, что он стал "распространенным"

.
10
ответ дан 30 November 2019 в 01:16
поделиться

Перечисления могут иметь изменяемое состояние. Обычно это не очень хорошая идея, потому что природа перечисления состоит в том, чтобы иметь ровно X версий типа Y, где X больше 1, поэтому манипулирование состоянием (кроме использования полей / свойств) становится немного кошмаром, поскольку каждый метод необходимо учитывать все возможные состояния всех констант перечисления X.

Но если вы все равно собираетесь определять перечисление только с одной константой; вы можете просто рассматривать эту единственную константу как обычный объект и делать все связанные с ней допущения. IOW: проблема наличия X версий состояния уходит, потому что X теперь 1.

3
ответ дан 30 November 2019 в 01:16
поделиться

(Этот ответ предполагает, что "принудительный" синглтон действительно то, что вы хотите, в отличие от фактического синглтона, управляемого вашей структурой DI (например, Guice's @Singleton ), что, вероятно, чаще является правильной идеей.)

Разложим ваш вопрос на два: действительно ли это широко распространено? Нет, не так широко, как должно быть. Это хорошая идея? Да!

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

Синглтон - это класс, который может иметь только фиксированный набор из N экземпляров, которые жестко запрограммированы в исходном коде. И N == 1.

Вот и все!

8
ответ дан 30 November 2019 в 01:16
поделиться

Нет перечисления не должны иметь изменяемое состояние. Статику обычно нельзя изменять. Синглтоны - это просто способ скрыть изменчивую статику. (Другое дело - объекты без сохранения состояния, реализующие интерфейс.)

1
ответ дан 30 November 2019 в 01:16
поделиться

Это плохая идея.

Он заставляет ваш класс наследовать от конкретного класса Enum . Это загрязняет вашу иерархию типов.

Тип ЭКЗЕМПЛЯР должен быть в точности Элвис ; это не может быть подтип Элвиса .

В более общем случае у вас нет свободы выбора способа создания экземпляра.

И с точки зрения синтаксиса, это действительно слишком много ввода?

public class Elvis {
    static public Elvis INSTANCE = new Elvis();
-4
ответ дан 30 November 2019 в 01:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: