Ein Observer dient dazu, den Zustand einer Klasse zu überwachen und bestimmte Maßnahmen einzuleiten, falls sich dieser verändert. Im Beispiel geht es darum einen Wert einer Klasse auf das Überschreiten eines Limits hin zu observieren und entsprechende Meldungen auszugeben.
Die Klasse Bar besitzt ein Attribut $_foo welches durch raiseFoo($value) um den übergebenen Wert $value erhöht werden kann.
Dieser Wert soll nun mit Hilfe des Observer Patterns auf das Überschreiten bestimmter Werte überwacht werden.
class BarClass { private $_foo = 0; public function raiseFoo($value) { $this->_foo += intval($value); echo 'Foo beträgt ',$this->_foo; $this->notify(); } public function getFoo() { return $this->_foo; } }
Die notwenidigen Interfaces für das Observer Pattern wurden für ein besseres Verständnis von Hand implementiert. Die in PHP5 verfügbare SPL-StandardPHPLibrary bietet diese Interfaces jedoch mit ähnlichem Naming bereits an. Ist also sichergestellt, dass die Applikation über diese verfügt, sollte auf die verfügbaren Interfaces SplSubject und SplObserver zurückgegriffen werden.
ObservableInterface
Interface für observierbare Klassen
interface ObservableInterface { // Add observer public function registerObserver(ObserverInterface $observer); // Delete observer public function unregisterObserver(ObserverInterface $observer); // Inform observer public function notify(); }
ObserverInterface
Interface für Observer
interface ObserverInterface { // Inform registered observers public function update(ObservableInterface $object); }
BarClass
Die Klasse Bar implementiert nun das ObservableInterface und wurde um die Möglichkeiten Observer bei sich zu registrieren und diese ebenfalls wieder zu de-registrieren erweitert. Weiterhin werden über die Methode notify() alle registrierten Observer durch deren update() Methoden informiert, indem die Klasse "sich selbst übergibt" (SCNR ;-) ).
class BarClass implements ObservableInterface { /** * Storage for observers */ private $_observers = array(); private $_foo = 0; /** * Add observer */ public function registerObserver(ObserverInterface $observer) { $this->_observers[] = $observer; } /** * Delete Observer */ public function unregisterObserver(ObserverInterface $observer) { unset($this->_observers[array_search($observer,$this->_observers)]); } /** * Inform observers */ public function notify() { foreach ($this->_observers as $observer) { $observer->update($this); } } public function raiseFoo($value) { $this->_foo += intval($value); echo 'Foo beträgt ',$this->_foo; $this->notify(); } public function getFoo() { return $this->_foo; } }
FooObserver
Ein Observer namens Foo, welcher die zu observierenden Klassen auf das Überschreiten eines bestimmten Attributs überwacht. Der Grenzwert $limit wird im Konstruktor übergeben. Sollte dieser im zu überwachenden Objekt überschritten werden, wird eine Meldung ausgegeben und der Observer de-registriert sich selbst beim Objekt um weitere Meldungen zu vermeiden.
class FooObserver implements ObserverInterface { private $_limit; public function __construct($limit) { $this->_limit = intval($limit); } public function update(ObservableInterface $object) { if ($object->getFoo() > $this->_limit) { echo 'Foo hat ',$this->_limit,' überschritten!'; $object->unregisterObserver($this); } } }
Und das ganze nun im Einsatz:
// Instanz auf zu observierende Klasse $bar = new BarClass(); // Observer, welcher auf Limit 500 prüft $bar->registerObserver(new Observer_FooObserver(500)); // Observer, welcher auf Limit 250 prüft $bar->registerObserver(new Observer_FooObserver(250)); // Wert erhöhen $bar->raiseFoo(200); $bar->raiseFoo(100); $bar->raiseFoo(100); $bar->raiseFoo(200);
Bar wird instanziiert und mit zwei Observern versehen. Diese haben zwei verschiedene Limits (500,250) übergeben bekommen, auf welche die Klasse observiert werden soll.
Anschließend wird der Wert von $bar durch raiseFoo(..) mehrmals erhöht, um die beiden Limits zu übersteigen.
Ausgabe:
Foo 200 Foo 300 Foo hat 250 überschritten! Foo 400 Foo 600 Foo hat 500 überschritten!
In der Ausgabe ist ersichtlich, dass beide Observer angeschlagen und die Überschreitung ihres Limits bemerkt und gemeldet haben. Da sich der Observer nach Festellung der Überschreitung selbstständig entfernt, wird vermieden, dass er bei jedem weiteren Aufruf von raiseFoo(..) eine Meldung ausgibt.




Neueste Kommentare
vor 7 Wochen 3 Tage
vor 8 Wochen 18 Stunden
vor 17 Wochen 6 Tage
vor 18 Wochen 1 Tag
vor 27 Wochen 6 Tage
vor 27 Wochen 6 Tage
vor 35 Wochen 2 Tage
vor 35 Wochen 2 Tage
vor 38 Wochen 4 Tage
vor 39 Wochen 2 Tage