2013-03-23 2 views
8

Как Блох состояния, в пункте 3 («Принудительно одноплодной собственности с частным конструктору или перечислимого типа») в Эффективное Java 2-е издание, тип перечисления Одноэлементная является лучшим способом реализовать синглтон. К сожалению, старый шаблон частного конструктора по-прежнему очень распространен и укоренен до такой степени, что многие разработчики не понимают, что я делаю, когда создаю перечислительные числа.аннотаций для Java перечислений одноточечного

Простой // Enum Singleton комментарий выше объявления класса помогает, но он по-прежнему оставляет возможность, что другой программист может прийти позже и добавить вторую константу в перечисление, нарушив свойство singleton. Для всех проблем, которые имеет подход частного конструктора, по-моему, он несколько более самодокументирован, чем одноэлементное перечисление.

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

@EnumSingleton // Annotation complains if > 1 enum element on EnumSingleton 
public enum EnumSingleton { 
    INSTANCE; 
} 

Кто-нибудь сталкивается с такой аннотацией для стандартной Java в публичных библиотеках где угодно? Или это то, что я прошу о невозможности в текущей системе аннотации Java?

UPDATE

Обойти я использую, по крайней мере, пока я не решу, на самом деле беспокоиться прокаткой своих собственных аннотаций, это поставить @SuppressWarnings("UnusedDeclaration") непосредственно перед INSTANCE поля. Он делает достойную работу, чтобы сделать код отличным от простого типа перечисления.

+1

Лучший способ должен быть в первую очередь прост и понятен с моей точки зрения. – kapand

ответ

2

Я не знает такую ​​аннотации в публичных библиотеках Java, но вы можете определить себе такую ​​аннотацию времени компиляции, которая будет использоваться для ваших проектов. Конечно, вам нужно написать обработчик аннотации для него и вызвать как-то APTant или maven), чтобы проверить ваши объявленные номины @EnumSingleton во время компиляции для предполагаемой структуры.

Вот ресурс о том, как писать и использовать compile time annotations.

3

Вы можете использовать что-то вроде этого -

public class SingletonClass { 
    private SingletonClass() { 
     // block external instantiation 
    } 

    public static enum SingletonFactory { 
     INSTANCE { 
      public SingletonClass getInstance() { 
       return instance; 
      } 
     }; 

     private static SingletonClass instance = new SingletonClass(); 
     private SingletonFactory() { 
     } 

     public abstract SingletonClass getInstance(); 
    } 
} 

И вы можете получить доступ к какому-либо другому классу, как -

SingletonClass.SingletonFactory.INSTANCE.getInstance(); 
+0

Спасибо! Это интересный подход, чтобы сочетать преимущества частных конструкторов. Безусловно, тот факт, что это синглтон гораздо более очевидный. :) Что-то еще, что происходит со мной, - это проверить длину EnumSingleton.values ​​() в собственном конструкторе по умолчанию enum. Затем я могу, по крайней мере, выбросить исключение RuntimeException, если какой-то небрежный человек попытается добавить еще одну константу в перечисление в какой-то момент. –

+0

@AndrewBissell Я думаю, что это лучший кандидат на единичный тест, поскольку модульные тесты предполагают помочь описать поведение класса. – Jazzepi

+0

@ Jazzepi Правильно! Я получил красивую трассировку стека с строкой «invokeExplosively», когда я попытался прочесть длину значений() до инициализации перечисления. :) Так много для этой идеи. –