PHP observer pattern and SPL

Citește postarea în română

Share on:

Observer pattern refers to a class called “subject” that has a list of dependents, called observers, and notifies them automatically each time an action is taking place.

A small example of why is used:

– let’s say we have a class with does someting:

 1class Actiune {
 2    private $val;
 3    function __construrct() {
 4        // someting in the constructor
 5    }
 6
 7    function change($val) {
 8        $this->val = $val;
 9    }
10}

Each time $val changes we want to call a method of an “observer” object:

 1class Actiune {
 2    private $val;
 3    function __construrct() {
 4         // someting in the constructor
 5    }
 6
 7    function change($val, $observator) {
 8        $this->val = $val;
 9        $observator->update($this);
10    }
11}

Theoretically is not bad, but the more methods there are so does the dependence grows bigger and each time we add a new observer object we must modify the class, with will probably result in chaos, which will be almost impossible to port.

Now, the observator pattern looks something like this:

diagrama

SPL (Standard PHP Library), which is well known for it’s defined iterators, comes with the interfaces SplSubject and SplObserver, for the subject and respectively the observer.

An implementation looks someting like this:

 1/**
 2 * the class which must be monitored
 3 */
 4class Actiune implements SplSubject {
 5    private $observatori = array();
 6    private $val;
 7
 8    /**
 9     * method to attach an observer
10     *
11     * @param SplObserver $observator
12     */
13    function attach(SplObserver $observator) {
14        $this->observatori[] = $observator;
15    }
16
17    /**
18     * method to detach an observer
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     * method that notifies the observer objects
32     */
33    function notify() {
34        foreach($this->observatori as $observator) {
35            $observator->update($this);
36        }
37    }
38
39    /**
40     * method for makeing changes in the class
41     *
42     * @param int $val
43     */
44    function update($val) {
45        echo 'updateing...';
46        $this->val = $val;
47        $this->notify();
48    }
49
50    /**
51     * public method with the subject's status
52     *
53     * @return int
54     */
55    function getStatus() {
56        return $this->val;
57    }
58}
59
60/**
61 * and observer class
62 */
63class Observator implements SplObserver {
64    function update(SplSubject $subiect) {
65        echo $subiect->getStatus();
66    }
67}
68
69// an observer instance
70$observator = new Observator();
71
72// an subject instance
73$subiect = new Actiune();
74
75// attaching an observer to the subject
76$subiect->attach($observator);
77
78// update subject
79$subiect->update(5);

What seems strange is that there isn’t any documentation on this SPL interfaces. Even on the Zend website there is an article PHP Patterns: The Observer Pattern which does not use SPL, but for something like namespaces there was documentation even before PHP 5.3 was out.