Niektóre problemy z singlami enum:
Zaangażowanie w strategię wdrażania
Zazwyczaj „singleton” odnosi się do strategii implementacji, a nie specyfikacji API. Bardzo rzadko Foo1.getInstance()publicznie deklaruje, że zawsze zwróci tę samą instancję. W razie potrzeby implementacja Foo1.getInstance()może ewoluować, na przykład zwracając jedną instancję na wątek.
Z Foo2.INSTANCEPublicznie oświadczam, że ten przypadek jest instancji i nie ma szans, by to zmienić. Strategia wdrażania posiadania pojedynczej instancji jest ujawniona i zobowiązana.
Ten problem nie jest paraliżujący. Na przykład Foo2.INSTANCE.doo()może polegać na lokalnym obiekcie pomocniczym wątku, aby skutecznie mieć instancję dla wątku.
Rozszerzanie klasy Enum
Foo2rozszerza super klasę Enum<Foo2>. Zwykle chcemy unikać superklas; zwłaszcza w tym przypadku narzucona Foo2superklasa nie ma nic wspólnego z tym, co Foo2powinno być. Jest to zanieczyszczenie dla hierarchii typów naszej aplikacji. Jeśli naprawdę chcemy superklasy, zwykle jest to klasa aplikacji, ale nie możemy, Foo2superklasa jest naprawiona.
Foo2dziedziczy niektóre zabawne metody instancji name(), cardinal(), compareTo(Foo2), które są po prostu mylące dla Foo2użytkowników. Foo2nie może mieć własnej name()metody, nawet jeśli ta metoda jest pożądana w Foo2interfejsie.
Foo2 zawiera także kilka zabawnych metod statycznych
public static Foo2[] values() { ... }
public static Foo2 valueOf(String name) { ... }
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
co wydaje się bezsensowne dla użytkowników. Singleton zazwyczaj nie powinien mieć metod statycznych pulbic (inaczej niż getInstance())
Serializacja
Singletony są bardzo częste. Te singletony zasadniczo nie powinny być serializowane. Nie mogę wymyślić żadnego realistycznego przykładu, w którym sensowne byłoby transportowanie stanowego singletonu z jednej maszyny wirtualnej na inną maszynę wirtualną; singleton oznacza „unikalny w obrębie maszyny wirtualnej”, a nie „unikalny we wszechświecie”.
Jeśli serializacja naprawdę ma sens dla stanowego singletonu, singleton powinien jawnie i precyzyjnie określić, co to znaczy deserializować singleton na innej maszynie wirtualnej, gdzie singleton tego samego typu może już istnieć.
Foo2automatycznie stosuje uproszczoną strategię serializacji / deserializacji. To tylko wypadek, który czeka. Jeśli mamy drzewo danych koncepcyjnie odnoszące się do zmiennej stanu Foo2w VM1 w t1, poprzez serializację / deserializację wartość staje się inną wartością - wartością tej samej zmiennej Foo2w VM2 w t2, tworząc trudny do wykrycia błąd. Ten błąd nie przydarzy się niemożliwym do znalezienia w Foo1ciszy.
Ograniczenia kodowania
Są rzeczy, które można zrobić w normalnych klasach, ale zabronione w enumklasach. Na przykład dostęp do pola statycznego w konstruktorze. Programista musi być bardziej ostrożny, ponieważ pracuje w specjalnej klasie.
Wniosek
Piggybacking na enum oszczędzamy 2 linie kodu; ale cena jest zbyt wysoka, musimy dźwigać wszystkie bagaże i ograniczenia wyliczeń, mimowolnie dziedziczymy „cechy” wyliczenia, które mają niezamierzone konsekwencje. Jedyną rzekomą zaletą - automatyczna serializacja - okazuje się być wadą.