Reply to comment

  • warning: array_fill(): Number of elements must be positive in /var/www/vhosts/benjaminradtke.com/httpdocs/includes/database.inc on line 253.
  • warning: implode(): Invalid arguments passed in /var/www/vhosts/benjaminradtke.com/httpdocs/includes/database.inc on line 253.
  • warning: array_keys() expects parameter 1 to be array, null given in /var/www/vhosts/benjaminradtke.com/httpdocs/modules/user/user.module on line 528.
  • user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')' at line 1 query: SELECT p.perm FROM role r INNER JOIN permission p ON p.rid = r.rid WHERE r.rid IN () in /var/www/vhosts/benjaminradtke.com/httpdocs/modules/user/user.module on line 528.

Observer Pattern

Your rating: None Average: 4 (2 votes)

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.

  1. class BarClass {
  2.  
  3. private $_foo = 0;
  4.  
  5. public function raiseFoo($value) {
  6. $this->_foo += intval($value);
  7. echo 'Foo beträgt ',$this->_foo;
  8. $this->notify();
  9. }
  10.  
  11. public function getFoo() {
  12. return $this->_foo;
  13. }
  14. }

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

  1. interface ObservableInterface {
  2.  
  3. // Add observer
  4. public function registerObserver(ObserverInterface $observer);
  5.  
  6. // Delete observer
  7. public function unregisterObserver(ObserverInterface $observer);
  8.  
  9. // Inform observer
  10. public function notify();
  11. }

ObserverInterface

Interface für Observer

  1. interface ObserverInterface {
  2.  
  3. // Inform registered observers
  4. public function update(ObservableInterface $object);
  5. }

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 ;-) ).

  1. class BarClass implements ObservableInterface {
  2.  
  3. /**
  4.   * Storage for observers
  5.   */
  6. private $_observers = array();
  7.  
  8. private $_foo = 0;
  9.  
  10. /**
  11.   * Add observer
  12.   */
  13. public function registerObserver(ObserverInterface $observer) {
  14. $this->_observers[] = $observer;
  15. }
  16.  
  17. /**
  18.   * Delete Observer
  19.   */
  20. public function unregisterObserver(ObserverInterface $observer) {
  21. unset($this->_observers[array_search($observer,$this->_observers)]);
  22. }
  23.  
  24. /**
  25.   * Inform observers
  26.   */
  27. public function notify() {
  28. foreach ($this->_observers as $observer) {
  29. $observer->update($this);
  30. }
  31. }
  32.  
  33. public function raiseFoo($value) {
  34. $this->_foo += intval($value);
  35. echo 'Foo beträgt ',$this->_foo;
  36. $this->notify();
  37. }
  38.  
  39. public function getFoo() {
  40. return $this->_foo;
  41. }
  42. }

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.

  1. class FooObserver implements ObserverInterface {
  2.  
  3. private $_limit;
  4.  
  5. public function __construct($limit) {
  6. $this->_limit = intval($limit);
  7. }
  8.  
  9. public function update(ObservableInterface $object) {
  10. if ($object->getFoo() > $this->_limit) {
  11. echo 'Foo hat ',$this->_limit,' überschritten!';
  12. $object->unregisterObserver($this);
  13. }
  14. }
  15. }

Und das ganze nun im Einsatz:

  1. // Instanz auf zu observierende Klasse
  2. $bar = new BarClass();
  3. // Observer, welcher auf Limit 500 prüft
  4. $bar->registerObserver(new Observer_FooObserver(500));
  5. // Observer, welcher auf Limit 250 prüft
  6. $bar->registerObserver(new Observer_FooObserver(250));
  7. // Wert erhöhen
  8. $bar->raiseFoo(200);
  9. $bar->raiseFoo(100);
  10. $bar->raiseFoo(100);
  11. $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:

  1. Foo 200
  2. Foo 300
  3. Foo hat 250 überschritten!
  4. Foo 400
  5. Foo 600
  6. 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.

Reply

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <abbr>
  • Lines and paragraphs break automatically.

More information about formatting options

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.

Tags