Home

Singleton - wzorzec projektowy

Czym są wzorce projektowe?

Wzorce projektowe są udokumentowanymi i sprawdzonymi sposobami na rozwiązanie często spotykanych problemów projektowych. Prawdopodobnie nieraz już trafiłeś na problem projektowy, którego rozwiązanie zajęło ci parę ładnych godzin. Zapewne problem rozwiązałeś i wielce prawdopodobne, że sam "odkryłeś" wzorzeć projektowy, który już wcześniej został odkryty przez innego programistę. Zatem po co marnować długie godziny na wynajdowanie koła od nowa?

Poznaj wzorce projektowe a wiele twoich problemów zniknie!

Singleton

Zacznijmy od najbardziej znanego, najprostszego w implementacji i okrytego najgorszą sławą wzorca o nazwie Singleton. Co do złej sławy to polecam artykuł. Jednak nie ma sensu na wstępie marudzić. Zatem...

Definicja:

Wzorzec Singleton zapewnia, że dana klasa będzie miała tylko i wyłącznie jedną instancję obiektu i zapewnia globalny punkt dostępu do tej instancji.


Zalety wzroca:

1. Masz gwarancję, że będziesz miał tylko i wyłącznie jedną instancję obiektu danej klasy
2. Pobieranie instancji klasy jest przeźroczyste - użytkownik nie wie czy instancja została właśnie utworzona czy istniała już wcześniej
3. Instancja klasy jest tworzona dopiero przy pierwszej próbie użycia - jeśli żaden komponent nie będzie potrzebował korzystać z klasy to jej instancja nie zostanie w ogóle utworzona, a co za tym idzie nie zostaną zmarnowane zasoby.

Wady:

1. Singleton jest trudny w testowaniu
2. Singletonu nie można rozszerzyć (z powodu zastosowania prywatnego konstruktora)
3. Singleton łamie zasadę SRP
4. Singleton łamie zasadę OCP

Kiedy używać?

Szkolny przykład zastosowania Singletonu to klasa odpowiadająca za połączenie z bazą danych. Jeśli jeśli masz wiele metod lub funkcji, które wykorzystują bazę danych to raczej nie chciałbyś aby w każdej z tych metod połączenie z bazą było otwierane i zamykane za każdym razem. Takie zachowanie po pierwsze powoduje narzut wydajnościowy a po drugie nie jest nam zwyczajnie do niczego potrzebne.

Rozwiązanie problemu

Złe:

W zasadzie problem tworzenia wielu instacji klasy odpowiadającej za połączenie z bazą danych mógłbyś rozwiązać w bardzo prosty, aczkolwiek bardzo "nieładny" sposób. W jednym miejscu aplikacji stworzyłbyś instancję tej klasy i przypisał ją do zmiennej globalnej. Główną wadą takiego rozwiązania jest niezaprzeczalne stwierdzenie, że "Globale to złoooo!". Kolejną wadą jest to, że takie rozwiązanie problemu nie daje ci gwarancji na to, że jakiś inny programista nie utworzy sobie bezpośrednio takiego obiektu bez twojej wiedzy. Zatem nie jest to dobry sposób, bo nie daje gwarancji istnienia tylko jednej instancji tej klasy.

Dobre, czyli wg. wzorca Singleton:


<?php
 
 class Singleton
 {
   private static $instance;
   private function __construct() {} // Blokujemy domyślny konstruktor publiczny
   private function __clone(){} // Uniemozliwia utworzenie kopii obiektu
 
   public static function getInstance ()
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
 }
 
 // Pobieramy instancję
 
 $singleton = Singleton::getInstance();
?>


źródło: wikisource

Pierwsze co rzuca się w oczy w implementacji klasy Singleton to prywatny konstruktor. Żadki to widok, a jednak w tym przypadku ma sens. Dzięki takiemu zabiegowi nie ma możliwości stworzenia instancji tej klasy za pomocą operatora new, czyli new Singleton.

Zobaczmy co się stanie gdy spróbujemy właśnie w taki sposób utworzyć obiekt klasy Singleton:

<?php 
 $singleton = new Singleton();
?>

Fatal error: Call to private Singleton::__construct()

Zatem jak widać nie uda nam się stworzyć obiektu Singleton za pomocą operatora new. Jedynym sposobem aby utworzyć obiekt jest wywołanie statycznej metody getInstance():


<?php  
 // Pierwsze użycie metody getInstance powoduje utworzenie nowego obiektu
 $singleton = Singleton::getInstance();
?>

Dodatkową gwarancję na unikalność instancji klasy Singleton daje nam to, że zablokowaliśmy możliwość klonowania obiektu.

To już wszystko. Wkrótce pojawią się artykuły przedstawiające kolejne wzorce projektowe.