Czym jest wzorzec Rejestr(Registry) i kiedy może się nam przydać?
Wzorzec Rejestru jest przydatny gdy chcemy mieć globalny dostęp do obiektów znajdujących się w jednym miejscu. Jaka jest więc różnica pomiędzy Rejestrem, a zastosowaniem zmiennych globalnych? Otóż dzięki użyciu Rejestru mamy kontrole nad dostępem do obiektów. Podstawowymi metodami rejestru będą metody rejestrujące obiekt oraz pobierające go. Można jeszcze, a wręcz powinno się dodać metodę, która wyrejestruje obiekt, ale w tym prostym przykładzie to pominę. Rejestracja obiektu i jego pobieranie zostaną zaimplementowane poprzez funkcje magiczne __get() oraz __set(). Są to funkcje wywoływane w klasie w momencie kiedy próbujemy dostać się do nieistniejącej zmiennej w klasie. Na potrzeby rejestru, stworzyłem 3 proste klasy o nazwach A, B i C, których zadaniem jest coś wyświetlić.
Implementacja wzorca Rejestru w PHP
class A { public function sayA() { echo 'a'; } } class B { public function sayB() { echo 'b'; } } class C { public function sayC() { echo 'C'; } }
Następnie przechodzę do tworzenia rejestru. W poprzednim artykule opisywałem wzorzec Singleton, z którego teraz skorzystam. Ponadto będzie nam potrzebna tablica, która przechowa obiekty w rejestrze. Tablica zadeklarowana jest jako static ponieważ potrzebujemy wyłącznie jednej tablicy.
Najważniejszymi metodami są metody __get oraz __set, które odpowiadają za rejestrację obiektu i jego pobranie.
Metoda __get() sprawdza czy obiekt istnieje w rejestrze i jeśli tak to go zwraca, a jeżeli nie istnieje to wyrzuca wyjątek, że obiekt nie istnieje.
Metoda __set() zapisuje obiekt($value) w rejestrze pod nazwą $object. W tej metodzie powinniśmy dodać sprawdzanie czy obiekt już istnieje w tablicy, na podobnej zasadzie jak w metodzie __get(), ale w tym prostym przykładzie to pominę.
Implementacja klasy Rejestr w PHP
class Registry { private static $instance; public static function getInstance() { if(self::$instance == null) self::$instance = new Registry(); return self::$instance; } private static $objects = array(); private function __construct() { } public function __get($key) { if(isset(self::$objects[$key]) == false) { throw new Exception('<br>Brak obiektu w rejestrze<br>'); } return self::$objects[$key]; } public function __set($object, $value) { self::$objects[$object] = $value; } }
Przykładowe użycie wzorca
Gdy już mamy zaimplementowany wzorzec rejestru możemy przetestować jak on działa. Tworzymy blok try catch ponieważ jedna z metod wyrzuca wyjątek. W bloku try tworzymy obiekty klas A, B oraz C. Pobieramy instancję rejestru.
Następnie zapisujemy pod nazwą a obiekt klasy A i analogicznie robimy to samo dla klas B oraz C. W następnych linia pobieramy obiekt B z rejestru do zmiennej $objectToTest oraz wywołujemy na nim jego metodę sayB(). Następnie wywołujemy funkcję doSomething(), która pobiera z Rejestru obiekt A i wywołuje jego metodę sayA(). Na końcu pobieramy obiekt D, który nie istnieje i zostanie rzucony wyjątek, który wyświetlamy.
try { $objA = new A(); $objB = new B(); $objC = new C(); $registry = Registry::getInstance(); $registry->a = $objA; $registry->b = $objB; $registry->c = $objC; $objectToTest = $registry->b; $objectToTest->sayB(); doSomething(); //dostep do niezarejsowanego obiektu $registry->d; } catch(Exception $e) { echo $e->getMessage(); } function doSomething() { Registry::getInstance()->a->sayA(); }
Podsumowowanie
Wzorzec rejestru bardzo ułatwia programowanie jednakże, nie powinien być nadużywany. Kod, który napisałem można rozwinąć poprzez implementacje interfejsów: Iterator, ArrayAccess, Countable, Serializable oraz lepszą obsługę wyjątków, powinniśmy też dodać metodę wyrejestrowującą obiekt z rejestru. Jako bardzo dobrą implementacje rejestru mogę polecić klasę Zend_Registry. Wchodzącą w skład frameworka Zend.
Zostaw komentarz