Claudiu Persoiu

Blog-ul lui Claudiu Persoiu


Archive for the ‘Observer pattern’ tag

PHP observer pattern si SPL

without comments

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:

class Actiune {
    private $val;
    function __construrct() {
        // ceva cod in constructor
    }

    function change($val) {
        $this->val = $val;
    }
}

De fiecare data cand se face modifica $val vrem sa se apeleze o metoda a unui obiect “observator”:

class Actiune {
    private $val;
    function __construrct() {
        // ceva cod in constructor
    }

    function change($val, $observator) {
        $this->val = $val;
        $observator->update($this);
    }
}

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:

diagrama

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:

/**
 * clasa care trebuie urmarita
 */
class Actiune implements SplSubject {
    private $observatori = array();
    private $val;

    /**
     * metoda atasare obiect observator
     *
     * @param SplObserver $observator
     */
    function attach(SplObserver $observator) {
        $this->observatori[] = $observator;
    }

    /**
     * metoda deatasare obiect observator
     *
     * @param SplObserver $observator
     */
    function detach(SplObserver $observator) {
        $observatori = array();
        foreach($this->observatori as $observatorul) {
            if($observatorul != $observator) $observatori[] = $observatorul;
        }
        $this->observatori = $observatori;
    }

    /**
     * metoda care notifica obiectele de tip observator
     */
    function notify() {
        foreach($this->observatori as $observator) {
            $observator->update($this);
        }
    }

    /**
     * metoda care face modificarea in clasa
     *
     * @param int $val
     */
    function update($val) {
        echo 'facem update...
';
        $this->val = $val;
        $this->notify();
    }

    /**
     * metoda publica care intoarce statusul obiectului
     *
     * @return int
     */
    function getStatus() {
        return $this->val;
    }
}

/**
 * o clasa observator
 */
class Observator implements SplObserver {
    function update(SplSubject $subiect) {
        echo $subiect->getStatus();
    }
}

// instanta observator
$observator = new Observator();

// instanta subiect
$subiect = new Actiune();

// atasare observator la subiect
$subiect->attach($observator);

// update subiect
$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.

Written by Claudiu Persoiu

4 August 2009 at 6:52 PM