Wzór twórczy: Singleton

Dec 04 2022
W tym artykule omówiono, w jaki sposób wzorzec Singleton wymusza, aby tylko jedna instancja klasy kiedykolwiek została wyprodukowana i istniała przez cały okres istnienia aplikacji. Co to jest? Singleton to wzorzec projektowy używany do tworzenia jedynej instancji klasy.

W tym artykule omówiono, w jaki sposób wzorzec Singleton wymusza, aby tylko jedna instancja klasy kiedykolwiek została wyprodukowana i istniała przez cały okres istnienia aplikacji.

Co to jest?

Singleton to wzorzec projektowy używany do tworzenia jedynej instancji klasy. Wzorzec singleton jest zwykle używany, gdy istnieje kilka przykładów, w których powinna istnieć tylko jedna instancja klasy i wymuszane jest ograniczenie. Na przykład pamięci podręczne, pule wątków i rejestry powinny mieć tylko jedną instancję.

Uczyń konstruktora prywatnym, aby mieć pewność, że tworzony jest tylko jeden obiekt klasy. W ten sposób tylko członkowie klasy mają dostęp do prywatnego konstruktora i nikt inny.

W prawdziwym świecie wzorzec Singleton zapewnia, że ​​istnieje tylko jedna instancja klasy i oferuje globalny punkt dostępu do niej.

Diagram klas

Diagram klas zawiera tylko jedną jednostkę.

Singel

Przykład

Załóżmy, że chcemy w naszym oprogramowaniu wymodelować oficjalny samolot prezydenta Stanów Zjednoczonych o nazwie Airforce One. Klasa Singleton jest najlepiej dopasowaną reprezentacją jednostki z tylko jedną instancją.

Oto kod naszej klasy singleton:

Wielowątkowość i Singleton

Ten kod działa tak długo, jak długo aplikacja jest jednowątkowa. Jeśli jednak wiele wątków uzyskuje dostęp do tej klasy, istnieje możliwość utworzenia różnych obiektów.

Na przykład:

  • Wątek A wywołuje metodę getInstancei stwierdza, że onlyInstance​​ma wartość null; jednak zanim będzie mógł utworzyć instancję, jest przełączany kontekst.
  • Teraz pojawia się wątek B i wywołuje getInstance, co zwraca AirforceOneobiekt.
  • Jeśli wątek A zostanie ponownie zaplanowany, zaczyna się psota. Wątek przeszedł już sprawdzanie warunku if-null i przystąpi do tworzenia nowego AirforceOneobiektu i przypisania go do onlyInstance. AirforceOneTeraz na wolności istnieją dwa różne obiekty, jeden z wątkiem A i jeden z wątkiem B.
  • Dodając synchronizeddo getInstance()metody, możesz osiągnąć bezpieczeństwo gwintu.
  • Inną opcją jest statyczna inicjalizacja instancji, gwarantująca bezpieczeństwo wątków.

Dwukrotnie sprawdzone blokowanie

Istnieją dwa istotne problemy z opisanymi powyżej podejściami: synchronizacja jest kosztowna, a inicjalizacja statyczna tworzy obiekt, nawet jeśli nie jest on używany w określonej aplikacji. Jeśli tworzenie obiektu jest drogie, inicjalizacja statyczna może kosztować nas wydajność.

Powyższe rozwiązanie oznacza, że ​​instancja singletonu jest niestabilna. Jednak ta implementacja metodologii JVM volatilenie będzie działać poprawnie w przypadku podwójnego sprawdzania blokowania i będziesz potrzebować innego podejścia do tworzenia singletonów.

Podwójnie sprawdzany idiom blokujący jest obecnie uważany za antywzorzec, a jego użyteczność przede wszystkim przeminęła, ponieważ czasy uruchamiania maszyny JVM przyspieszyły.

Inne przykłady

Java API udostępnia nam następujące singletony:

java.lang.Środowisko wykonawcze

java.awt.Desktop

Zastrzeżenia

Możesz podklasować klasę singleton, chroniąc konstruktora zamiast private. Jednak w każdych okolicznościach istnieją lepsze wybory niż ten. W takich sytuacjach programiści mogą utworzyć rejestr pojedynczych elementów dla wszystkich podklas. Metoda getInstance może przyjąć parametr lub użyć zmiennej środowiskowej, aby zwrócić żądany obiekt singleton. Rejestr utrzymuje mapowanie nazw łańcuchów na pojedyncze obiekty.

Inne artykuły z serii Creational Pattern