Singleton – Wzorzec Projektowy

Singleton jest wzorcem projektowym o którym napisano już bardzo dużo. Głównie można na internecie przeczytać o tym, że Singletonu to najlepiej unikać. Z mojego doświadczenia Singleton jest również częstym pytaniem podczas rozmowy na początkującego programisty.

James ma polską fabrykę, która zajmuje się produkcją części oraz składaniem z tych części hulajnóg.

James w pewnym momencie stwierdził, że chciałby mieć dokładne raporty z każdej operacji, która miały miejsce u niego w fabryce. Wszystkie raporty mają być zapisane w jednym pliku w tym samym miejscu na dysku.

Aby sprostać wymaganiom James została zaimplementowana klasa Raport.

Dane do raportu będę dodawane w konstruktorach nowo tworzonych elementów hulajnogi. Za każdym razem razem kiedy będzie wywołany konstruktor od kierownicy, naklejki, hamulców, kółka oraz hulajnogi będą dodawane nowe informacje do raportu. Rozwiążmy ten problem najprościej jak się da.

Rozwiązanie to jest kiepskiej jakości. Dlaczego?

Zmieńmy trochę aktualne rozwiązanie. Stwórzmy obiekt Raport w najwyższej warstwie w programu, a potem będziemy przekazywać referencje do obiektów niżej.

Rozwiązanie lepsze, ale spójrz proszę ile pracy nas to kosztowało. Wpierw tworzę Raport potem przekazuję go do klasy HalaZCzesciami. Potem z HaliZCzesciami przekazuję obiekt Raport do kierownicy, hamulców itd. Muszę pamiętać też, aby przekazać Raport  do HaliSkladajacej, a z Hali składającej do konstruktora Hulajnogi. Dużo pracy. Czy można prościej?

Singleton jako rozwiązanie problemu

Singleton wymusza dzięki składni języka możliwość stworzenia tylko jednej instancji obiektu danej klasy.

W tym momencie nie można po prostu napisać w programie konstruktora klasy Raport, ponieważ konstruktor jest prywatny. Aby dostać instancję klasy należy wywołać metodę statyczną GetInstance.

Metoda GetInstance  sprawdza, czy pole _raport jest nullem. Czyli innymi słowy sprawdzane jest czy obiekt klasy Raport  był już zainicjowany. Jeżeli nie był, to tworzony jest pierwszy i ostatni raz  w czasie działania tego programu. Następnie instancja jest przypisana do pola _raport . Każde kolejne wywołanie metody GetInstance zwróci już istniejącą już instancję klasy Raport.

Dzięki takiemu rozwiązaniu możemy użyć takiego rozwiązania zapisywania do pliku informacji:

Wywoływana jest metoda GetInstance, która zwraca instancję klasy Raport, a następnie wykonujemy na niej operację.

Dzięki temu nasz program może wyglądać teraz tak:

Singleton jest wzorcem kontrowersyjnym, który może budzić różnego rodzaju pytania.

Kiedy używać Singletonu?

Wiele przeczytałem na Internecie o tym jaki ten wzorzec projektowy jest zły i niedobry, bo:

  • Łamie Zasadę Jednej Odpowiedzialności,
  • Powoduje, że kod jest trudny do testowania,
  • Jest jak zmienna globalna, klasa statyczna, co uchodzi ogólnie za złą praktykę,
  • Występuje tak zwany tight coupling.

Skoro taki wzorzec projektowy powstał musi mieć gdzieś swoje zastosowanie. Więc przyjrzyjmy się jakie założenia musi spełniać kandydat na Singletona:

  • Kontroluje dostęp do współdzielonego w programie zasobu (np. plik)
  • Dostęp do zasobu jest potrzebny w różnych miejscach w systemie (potrzebny jest w hali z częściami, oraz w miejscu gdzie składane są hulajnogi)
  • Może istnieć tylko jedne obiekt

Jaka jest różnica pomiędzy Singletonem, a klasą statyczną?

  • Singleton może implementować interfejs, a klasa statyczna nie. Dzięki temu Singleton może być przekazany potem jako parametr i traktować go jako zwykłą klasę (oszczędzamy czas na wywołanie metody GetInstance)
  • Singleton można dziedziczyć
  • Singleton działa na zasadzie lazy loading, a klasa statyczna jest tworzona zaraz przy kompilacji programu
  • Singleton ma konstruktor, klasa statyczna nie
  • Singleton może mieć tylko jedną instancję, dzięki czemu można łatwiej kontrolować instancję, klasa statyczna nie ma żadnego stanu

 

Singleton – przydatne linki

Różnica pomiędzy klasą statyczną, a Singletonem, nr 1

Różnica pomiędzy klasą statyczną, a Singletonem, nr 2

Różnica pomiędzy klasą statyczną, a Singletonem, nr 3

Kiedy używać Singletonu?

Powered by: Wordpress