Wyczytałem, że jest możliwe zaimplementowanie Singleton
w Javie przy użyciu Enum
np .:
public enum MySingleton {
INSTANCE;
}
Ale jak to działa? W szczególności Object
należy utworzyć instancję. Tutaj, jak jest MySingleton
tworzony? Kto to robi new MySingleton()
?
java
design-patterns
enums
singleton
Anand
źródło
źródło
INSTANCE
jest taki sam jakpublic static final MySingleton INSTANCE = new MySingleton();
.Odpowiedzi:
To,
ma niejawny pusty konstruktor. Zamiast tego wyraź to wyraźnie,
Jeśli następnie dodałeś kolejną klasę za pomocą
main()
metody takiej jakZobaczyłbyś
enum
pola są stałymi czasu kompilacji, ale są instancjami swojegoenum
typu. Są one konstruowane, gdy typ wyliczenia jest przywoływany po raz pierwszy .źródło
private
Modyfikator nie ma żadnego znaczenia dlaenum
konstruktora i jest całkowicie zbędne.enum
Typ jest specjalnym typemclass
.Twoja
enum
wola zostanie faktycznie skompilowana do czegoś takiego jakGdy kod uzyskuje dostęp po raz pierwszy
INSTANCE
, klasaMySingleton
zostanie załadowana i zainicjowana przez maszynę JVM. Ten proces inicjalizujestatic
pole powyżej jeden raz (leniwie).źródło
public enum MySingleton { INSTANCE,INSTANCE1; }
a następnieSystem.out.println(MySingleton.INSTANCE.hashCode()); System.out.println(MySingleton.INSTANCE1.hashCode());
drukuje różne hashcodes. Czy to oznacza, że powstają dwa obiekty MySingleton?enum
stałe różnicowe .W tej książce o najlepszych praktykach dotyczących języka Java autorstwa Joshua Blocha można znaleźć wyjaśnienie, dlaczego należy wymusić właściwość Singleton za pomocą prywatnego konstruktora lub typu Enum. Rozdział jest dość długi, więc podsumowując:
Skonfigurowanie klasy jako singletona może utrudnić testowanie jej klientów, ponieważ nie jest możliwe zastąpienie pojedynczej implementacji fałszywej, chyba że implementuje interfejs, który służy jako jego typ. Zalecanym podejściem jest implementacja Singletonów poprzez proste utworzenie typu wyliczenia z jednym elementem:
To podejście jest funkcjonalnie równoważne z podejściem w terenie publicznym, z tym wyjątkiem, że jest bardziej zwięzłe, zapewnia maszynę do serializacji za darmo i zapewnia żelazną gwarancję przed wielokrotnymi instancjami, nawet w obliczu wyrafinowanych ataków serializacji lub odbicia.
źródło
Podobnie jak wszystkie instancje wyliczenia, Java tworzy instancję każdego obiektu, gdy klasa jest ładowana, z pewną gwarancją, że jest ona tworzona dokładnie raz na JVM . Potraktuj
INSTANCE
deklarację jako publiczne statyczne pole końcowe: Java utworzy instancję obiektu przy pierwszym odwołaniu do klasy.Instancje są tworzone podczas statycznej inicjalizacji, która jest zdefiniowana w specyfikacji języka Java, sekcja 12.4 .
Co jest warte, Joshua Bloch szczegółowo opisuje ten wzorzec jako punkt 3 w Effective Java Second Edition .
źródło
Ponieważ Singleton Pattern polega na posiadaniu prywatnego konstruktora i wywołaniu jakiejś metody do sterowania instancjami (jak niektóre
getInstance
), w Enums mamy już niejawny prywatny konstruktor.Nie wiem dokładnie, w jaki sposób JVM lub jakiś kontener kontroluje wystąpienia naszego
Enums
, ale wydaje się, że już używa niejawnegoSingleton Pattern
, różnica polega na tym, że nie wywołujemy agetInstance
, po prostu wywołujemy Enum.źródło
Jak do pewnego stopnia wspomniano wcześniej, wyliczenie jest klasą Java ze specjalnym warunkiem, że jej definicja musi zaczynać się od co najmniej jednej „stałej wyliczenia”.
Poza tym, a wyliczenia nie mogą być rozszerzane ani używane do rozszerzania innych klas, wyliczenie jest klasą jak każda inna klasa i można jej używać, dodając metody poniżej definicji stałych:
Dostęp do metod singletona można uzyskać w następujący sposób:
Użycie wyliczenia zamiast klasy polega, jak wspomniano w innych odpowiedziach, głównie na bezpieczną wątkowo instancję singletona i gwarancję, że będzie to zawsze tylko jedna kopia.
I, być może, co najważniejsze, to zachowanie jest gwarantowane przez samą maszynę JVM i specyfikację Java.
Oto sekcja ze specyfikacji Java na temat zapobiegania wielu wystąpieniom instancji wyliczeniowej:
Warto zauważyć, że po utworzeniu instancji wszelkie problemy związane z bezpieczeństwem wątków muszą być obsługiwane jak w każdej innej klasie za pomocą słowa kluczowego synchronized itp.
źródło