Наскоро се задълбочихте в шаблона за проектиране на singleton , How да го внедрите в Java и за Howво служи. Но Howво ще стане, ако ви кажа, че Java идва със собствен сингълтон веднага след като е готов? Заинтригуван? Тогава нека се потопим.

Вероятно вече знаете за класа Enum . Има специална функция, която трябва да знаете. По-конкретно, Enum имплементира модела на единичния дизайн. Тази опция е почти същата като единичния подход, включващ публично поле.

Singleton като enum:


public enum Device {   
    PRINTER	
} 
    

Singleton като публична променлива:


public class Printer {   
    public static final Printer PRINTER = new Printer();   
    private Printer() {
    }
//…
}
    

Подходът enum е по-компактен от подхода на публичното поле, тъй като не е необходимо да пишем наша собствена реализация. Най-важното е, че enum-ите нямат проблеми със сериализацията.

Сериализацията на enum работи по различен начин в сравнение с обикновените обекти: само стойността на името на enum се сериализира. По време на десериализацията методът се използва с десериализираното име за получаване на екземпляр. Освен това enum може да ви предпази от атаки с отражение .

Ще научите повече за отражението в уроците във втория модул, където ще изследваме API за отражение .

Java забранява инстанцирането на enums — ограничение, заложено в изпълнението на метода newInstance на класа Constructor , който често се извиква при създаване на обекти чрез отражение.

Извадка от code от Constructor.newInstance . Използва се за създаване на enum :


if ((clazz.getModifiers() & Modifier.ENUM) != 0)
    throw new IllegalArgumentException("Cannot reflectively create enum objects");
    

Недостатъците на използването на enum за създаване на сингълтън включват:

  • Липса на мързелива инициализация, тъй като обектът се създава незабавно и инициализацията не може да бъде отложена.

  • Други класове не могат да бъдат удължавани. Тоест, в случаите, когато трябва да наследите друг клас, няма да работи да използвате enum като singleton. В такива случаи трябва да се обърнем към другите опции за внедряване, които вече са ни познати: статичен метод or публична променлива.

  • Когато използвате enum като сингълтън, можете да използвате само едно поле enum .


public enum Device extends Electricity { 
    PRINTER 
}
    

Този code ще ни даде грешка при компorране:

Не е позволена клауза за разширяване за enum

Но ако трябва да внедрим интерфейс, няма проблем, тъй като enum може да реализира интерфейси:


public enum Device implements Electricity { 
    PRINTER 
}
    

Ако не е необходимо да използвате наследяване, най-добре е да приложите единичния модел чрез enum . Ние не сме сами в препоръчването на това – самият Джошуа Блок също го прави .

Този подход за внедряване ви дава удобство, компактност, сериализация извън кутията, защита от атаки на отражение и уникалност — всичко, от което се нуждае един добър сингълтън!