Деякі проблеми з перерахунком синглів:
Прихильність до стратегії впровадження
Як правило, "одиночний" відноситься до стратегії реалізації, а не до специфікації API. Дуже рідко Foo1.getInstance()публічно заявляти, що завжди повертає той самий екземпляр. За потреби реалізація Foo1.getInstance()може розвиватися, наприклад, для повернення одного екземпляра на потік.
З Foo2.INSTANCEми публічно заявляємо , що даний екземпляр екземпляр, і немає жодних шансів , щоб змінити це. Стратегія впровадження одного екземпляра піддається і зобов'язана.
Ця проблема не калічить. Наприклад, Foo2.INSTANCE.doo()можна покластися на локальний помічник об'єкта потоку, щоб ефективно мати екземпляр на один потік.
Розширення класу Enum
Foo2розширює супер клас Enum<Foo2>. Зазвичай ми хочемо уникати суперкласів; особливо в цьому випадку примусовий суперклас Foo2не має нічого спільного з тим, що Foo2має бути. Це забруднення для ієрархії типів нашої програми. Якщо ми справді хочемо суперкласу, зазвичай це клас додатків, але ми не можемо, Foo2суперклас це виправлено.
Foo2успадковує такі кумедні методи екземплярів name(), cardinal(), compareTo(Foo2), які просто плутають Foo2користувачів. Foo2не може мати власний name()метод, навіть якщо цей метод бажаний в Foo2інтерфейсі Росії.
Foo2 також містить деякі кумедні статичні методи
public static Foo2[] values() { ... }
public static Foo2 valueOf(String name) { ... }
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
що видається користувачам безглуздим. Однотонний звичайно не повинен мати пульбічних статичних методів (крім getInstance())
Серіалізація
Дуже часто зустрічається сингл. Ці одинаки, як правило, не повинні бути серіалізаційними. Я не можу придумати жодного реалістичного прикладу, де має сенс транспортувати великолепний сингл від одного ВМ до іншого ВМ; сингтон означає "унікальний всередині ВМ", а не "унікальний у Всесвіті".
Якщо серіалізація справді має сенс для симпатичного синглтона, синглтон повинен чітко і точно вказати, що означає десеріалізація синглетона в іншій ВМ, де сингл однотипного типу вже може існувати.
Foo2автоматично зобов'язується до спрощеної стратегії серіалізації / десеріалізації. Це просто нещасний випадок, який чекає. Якщо у нас є дерево даних, що концептуально посилається на змінну стану Foo2в VM1 на t1, через серіалізацію / десеріалізацію значення стає іншим значенням - значенням тієї ж змінної Foo2в VM2 при t2, створюючи важко виявити помилку. Ця помилка не трапиться з невідомими Foo1мовчки.
Обмеження кодування
Є речі, які можна робити в звичайних класах, але забороняти на enumзаняттях. Наприклад, доступ до статичного поля в конструкторі. Програміст повинен бути більш обережним, оскільки працює в спеціальному класі.
Висновок
За допомогою копіювання на enum ми зберігаємо 2 рядки коду; але ціна занадто висока, нам доводиться нести всі сумки та обмеження переліків, ми ненавмисно успадковуємо "риси" перерахунків, які мають непередбачувані наслідки. Єдина передбачувана перевага - автоматична серіалізація - виявляється недоліком.