Singleton
Koncepcja singletonu
Singleton to klasa, która może utworzyć tylko jeden egzemplarz. Typowymi przykładami singletonów są obiekty bezstanowe lub unikalne komponenty systemu. Jednak klasy singleton mają problem z testowalnością, chyba że typ jest zdefiniowany jako interfejs, a jego implementacja jest definiowana oddzielnie.
Sposoby tworzenia singletonów
Metoda z publicznym statycznym członkiem będącym polem finalnym
Prywatny konstruktor jest wywoływany tylko raz podczas inicjalizacji instancji Elvis, gwarantując, że jest to jedyny egzemplarz w całym systemie. Należy jednak pamiętać, że za pomocą AccessibleObject.setAccessible() można wywołać prywatny konstruktor. Można temu zapobiec, rzucając wyjątek podczas próby utworzenia drugiego obiektu.
- Zalety
- Fakt, że dana klasa jest singletonem, jest jasno widoczny w API.
- Prostota.
Metoda z publiczną statyczną metodą fabryczną
Oprócz modyfikacji za pomocą refleksji, ta metoda również gwarantuje, że w całym systemie istnieje tylko jeden egzemplarz. Jedyną różnicą jest zmiana pola na private i użycie statycznej metody fabrycznej do zwracania obiektu.
- Zalety
- Możliwość zmiany na nie-singletona bez modyfikacji API.
- Na przykład statyczna metoda fabryczna może zwracać różne instancje dla każdego wątku.
- Możliwość zmiany na generyczną fabrykę singletonów.
- Odwołanie do metody statycznej fabryki może być użyte jako dostawca.
- Na przykład zamiast Elvis::getInstance można użyć Supplier<Elvis>.
- Możliwość zmiany na nie-singletona bez modyfikacji API.
Jeśli nie ma potrzeby korzystania z powyższych zalet, lepiej jest użyć pierwszej metody.
Metoda z użyciem typu wyliczeniowego
Najbardziej pożądana metoda to użycie typu wyliczeniowego. W porównaniu z dwoma poprzednimi metodami jest ona bezpieczniejsza przed atakami za pomocą refleksji i ma czystszy kod. Ponadto, jak zostanie to opisane poniżej, dwie poprzednie metody mają wadę, że wymagają dodatkowego kodu podczas serializacji.
Należy jednak pamiętać, że podczas gdy singleton utworzony w ten sposób może dziedziczyć interfejsy, nie może dziedziczyć klas.
Punkty, na które należy zwrócić uwagę podczas serializacji klasy singleton
Jeśli chcesz serializować klasę singleton utworzoną za pomocą pierwszej lub drugiej metody, oprócz prostego zaimplementowania Serializable musisz zadeklarować wszystkie pola instancji jako transient i zastąpić metodę readResolve().
Komentarze0