2010-06-23 6 views
20

Pozycja 3 w Josh Block Efektywna Java (Egzekwowanie właściwości Singleton przy użyciu prywatnego konstruktora lub modułu wyliczającego) wspomina, że ​​"Chociaż to podejście nie zostało jeszcze powszechnie przyjęte, jednoelementowy typ wyliczeniowy jest najlepszym sposobem wdrożenia singel."Czy jednolity element typu Enum Singleton jest powszechnie przyjętym dobrym pomysłem?

Przykład:

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

dalej: „Takie podejście jest funkcjonalnym odpowiednikiem podejścia polu publicznym, z wyjątkiem, że jest bardziej zwięzły, zapewnia maszynerię serializacji za darmo i stanowi żelazną gwarancję przeciwko stwardnieniu instancji, nawet w obliczu wyrafinowanych ataków serializacji lub refleksji. "

Największym minusem, jaki widzę, jest: czy nazwy nie mają być zmienne? Wydaje się, że często używa się Singleton ze stanem.

Czy ten wzór rzeczywiście stał się bardziej powszechny od daty publikacji (wydanie drugie opublikowane w 2008 r.)?

+0

Czy jestem jedyną osobą, która czuje się niekomfortowo, jak wyliczanka w języku Java może zachowywać się jak zajęcia? Wygląda na to, że Java postanowiła pozbyć się "naturalnie wyglądających typów", które można zrobić w C++, przez przeciążanie metod, i zamieniła proste wyliczenia w tę dziwną plamę. – Uri

+1

C++ podejścia wylicza jako rozszerzenie użycia ints do przełączania, więc są one bardzo proste konstrukcje. Z drugiej strony w języku Java wyliczenia są pomyślane jako legalne klasy z całą funkcjonalnością, która się z nimi wiąże, różniące się tylko jednym (głównym) ograniczeniem tworzenia. Mają tę samą nazwę, ponieważ ich zastosowania nakładają się na pewne ważne obszary, ale uważaj na zbyt bliskie ich porównywanie - są to bardzo różne bestie. – tlayton

+1

@Uri, 'enum's w Javie nie tylko zachowują się jak klasy, one _ są_ klasami. Wszystkie one domyślnie rozszerzają 'java.lang.Enum'. – Pops

Odpowiedz

10

Podczas gdy wyliczenia nie są ogólnie podane jako zmienne, fakt ten opiera się na założeniach, w jaki sposób zostanie użyte wyliczenie. Chociaż te założenia zwykle się utrzymują, nie zawsze tak jest, a jednym z takich przypadków, w których nie są, jest stworzenie Singleton.

Chociaż nie jest to najczęstsze użycie wyliczeń, uzasadnione jest posiadanie wyliczenia z możliwym do zmiany stanem, choć możesz chcieć wskazać ten fakt w swoim kodzie, aby każdy inny programista, który mógłby na nie patrzeć, nie być zdezorientowanym.

Jeśli chodzi o popularność tego wzoru, widziałem go dość często, ale nie tak bardzo, że powiedziałbym, że stał się "powszechny".

3

Emulatory mogą mieć stan zmienny. Zazwyczaj nie jest to dobry pomysł, ponieważ natura wyliczenia polega na tym, by mieć dokładnie X wersji typu Y, gdzie X jest większe niż 1, więc żonglowanie stanem (inne niż używanie pól/właściwości) staje się koszmarem, ponieważ każda metoda musi brać pod uwagę wszystkie możliwe stany wszystkich stałych X enum.

Ale jeśli zamierzasz zdefiniować wyliczenie z tylko jedną stałą i tak; możesz po prostu traktować tę pojedynczą stałą jako zwykły obiekt i tworzyć wszystkie założenia, które jej towarzyszą. IOW: problem z posiadaniem wersji X stanu odchodzi, ponieważ X jest teraz 1.

8

(Odpowiedź ta zakłada, że ​​„wymuszane” Singleton jest naprawdę co chcesz, a nie de facto Singleton zarządzane przez ramy DI (np Guice na @Singleton), który jest prawdopodobnie częściej dobry pomysł).

Aby rozłożyć pytanie na dwie części: Czy jest naprawdę powszechnie przyjęty? Nie, nie tak szeroko, jak być powinno. Czy to dobry pomysł? Tak!

Wyliczenie Java jest klasą, która może mieć tylko ustalony zestaw wystąpień N, które są zakodowane w źródle.

Singleton to klasa, która może mieć tylko ustalony zestaw N instancji, które są zakodowane w źródle. I N == 1.

To takie proste!

1

Nie powinny mieć stanu zmiennego. Statyka nie powinna być zwykle zmienna. Singletony to tylko sposoby na zaciemnienie statyki.(Obiekty bezstanowe, które implementują interfejs, to inna sprawa.)

-3

To nie jest dobry pomysł.

Zmusza klasę do odziedziczenia po konkretnej klasie Enum. To zanieczyszcza twoją hierarchię typów.

Typ INSTANCE musi być dokładnie Elvis; nie może to być podtyp Elvis.

Generalnie nie masz żadnej swobody w wyborze instancji instancji.

Czy składnia jest naprawdę zbyt piskliwa?

public class Elvis { 
    static public Elvis INSTANCE = new Elvis(); 
+4

Jeśli uważasz, że jest to odpowiednik tego, co tu wpisałeś, bardzo polecam przeczytanie artykułu o EJ. Nikt nie zmusza cię do ujawnienia Elvisa jako Elvisa. Możesz go wyeksponować (za pomocą metody) jako dowolną supertype, a to jest dobra ogólna praktyka, ponieważ pozostawia ci swobodę w używaniu leniwej inicjalizacji, gdy wybierzesz. To wywołuje jedną z twoich obaw, a co oznacza "zanieczyszcza twoją hierarchię typów"? –

Powiązane problemy