-
Observer pattern se refera la un obiect “subiect” care are asociata o lista de obiecte dependente, numite observatori, pe care le apeleaza automat de fiecare data cand se intampla o actiune.
Un mic exemplu de ce se foloseste:
– sa zicem ca avem o clasa pe care se fac niste modificari:
1class Actiune { 2 private $val; 3 function __construrct() { 4 // ceva cod in constructor 5 } 6 7 function change($val) { 8 $this->val = $val; 9 } 10}
De fiecare data cand se face modifica $val vrem sa se apeleze o metoda a unui obiect “observator”:
1class Actiune { 2 private $val; 3 function __construrct() { 4 // ceva cod in constructor 5 } 6 7 function change($val, $observator) { 8 $this->val = $val; 9 $observator->update($this); 10 } 11}
Teoretic nu suna rau, dar cu cat sunt mai multe metode cu atat exista o dependenta mai mare si de fiecare data cand se adauga un obiect nou de tip observator trebuie modificata clasa, avand toate sansele sa rezulte intr-un haos aproape imposibil de portat.
Acum observator pattern arata cam asa:
SPL (Standard PHP Library), care este bine cunoscut pentru iteratorii definiti, vine cu interfetele SplSubject si SplObserver, pentru subiect respectiv observator.
O implementare arata cam asta:
1/** 2 * clasa care trebuie urmarita 3 */ 4class Actiune implements SplSubject { 5 private $observatori = array(); 6 private $val; 7 8 /** 9 * metoda atasare obiect observator 10 * 11 * @param SplObserver $observator 12 */ 13 function attach(SplObserver $observator) { 14 $this->observatori[] = $observator; 15 } 16 17 /** 18 * metoda deatasare obiect observator 19 * 20 * @param SplObserver $observator 21 */ 22 function detach(SplObserver $observator) { 23 $observatori = array(); 24 foreach($this->observatori as $observatorul) { 25 if($observatorul != $observator) $observatori[] = $observatorul; 26 } 27 $this->observatori = $observatori; 28 } 29 30 /** 31 * metoda care notifica obiectele de tip observator 32 */ 33 function notify() { 34 foreach($this->observatori as $observator) { 35 $observator->update($this); 36 } 37 } 38 39 /** 40 * metoda care face modificarea in clasa 41 * 42 * @param int $val 43 */ 44 function update($val) { 45 echo 'facem update... 46'; 47 $this->val = $val; 48 $this->notify(); 49 } 50 51 /** 52 * metoda publica care intoarce statusul obiectului 53 * 54 * @return int 55 */ 56 function getStatus() { 57 return $this->val; 58 } 59} 60 61/** 62 * o clasa observator 63 */ 64class Observator implements SplObserver { 65 function update(SplSubject $subiect) { 66 echo $subiect->getStatus(); 67 } 68} 69 70// instanta observator 71$observator = new Observator(); 72 73// instanta subiect 74$subiect = new Actiune(); 75 76// atasare observator la subiect 77$subiect->attach($observator); 78 79// update subiect 80$subiect->update(5);
Ce mi se pare mie ciudat este ca nu exista o documentatie pentru aceste interfetele din SPL. Chiar pe site-ul zend exista un articol PHP Patterns: The Observer Pattern care nu foloseste SPL, iar asta in masura in care exista documentatie pentru namespaces chiar inainte sa apara PHP 5.3.