. PHP Design Patterns . PHP Design Patterns Observer

PHP Design Patterns Observer

About the Observer

In the Observer pattern a subject object will notify an observer object if the subject's state changes.

In this example, the PatternSubject is the subject, and the PatternObserver is the observer. For the observer to be notified of changes in the subject it must first be registered with the subject using the attach method. For the observer to no longer be notified of changes in the subject it must be unregistered with the detatch method.

When the subject changes it calls the observer's update method with itself. The observer can then take the subject and use whatever methods have been made available for it to determine the subjects current state.

The Observer Pattern is often called Publish-Subscribe, where the subject would be the publisher, and the observer would be the subscriber.

AbstractObserver.php


//copyright Lawrence Truett and FluffyCat.com 2006, all rights reserved

  include_once('AbstractSubject.php');
  
  abstract class AbstractObserver {

    abstract function update(AbstractSubject $subject_in);

  }


download source, use right-click and "Save Target As..." to save with a .php extension.

AbstractSubject.php


//copyright Lawrence Truett and FluffyCat.com 2006, all rights reserved

  include_once('AbstractObserver.php');

  abstract class AbstractSubject {

    abstract function attach(AbstractObserver $observer_in);
    abstract function detach(AbstractObserver $observer_in);

    abstract function notify();

  }


download source, use right-click and "Save Target As..." to save with a .php extension.


PatternObserver.php


//copyright Lawrence Truett and FluffyCat.com 2006, all rights reserved

  include_once('AbstractObserver.php');
  include_once('PatternSubject.php');
  define('BR', '<'.'BR'.'>');

  class PatternObserver extends AbstractObserver {

    public function __construct() {
    }

    public function update(AbstractSubject $subject) {
      echo BR.BR;
      echo '*IN PATTERN OBSERVER - NEW PATTERN GOSSIP ALERT*'.BR;
      echo ' new favorite patterns: '.$subject->getFavorites().BR;
      echo '*IN PATTERN OBSERVER - PATTERN GOSSIP ALERT OVER*'.BR;      
    }

  }


download source, use right-click and "Save Target As..." to save with a .php extension.

PatternSubject.php


//copyright Lawrence Truett and FluffyCat.com 2006, all rights reserved

  include_once('AbstractSubject.php');
  include_once('PatternObserver.php');

  class PatternSubject extends AbstractSubject {

    private $favoritePatterns = NULL;

    private $observers = array();

    function __construct() {
    }

    function attach(AbstractObserver $observer_in) {
      //could also use array_push($this->observers, $observer_in);
      $this->observers[] = $observer_in;
    }

    function detach(AbstractObserver $observer_in) {
      //$key = array_search($this->observers, $observer_in);
      foreach($this->observers as $okey => $oval) {
        if ($oval == $observer_in) { 
          unset($this->observers[$okey]);
        }
      }
    }

    function notify() {
      foreach($this->observers as $obs) {
        $obs->update($this);
      }
    }

    function updateFavorites($newFavorites) {
      $this->favorites = $newFavorites;
      $this->notify();
    }

    function getFavorites() {
      return $this->favorites;
    }

  }


download source, use right-click and "Save Target As..." to save with a .php extension.

testObserver.php


//copyright Lawrence Truett and FluffyCat.com 2006, all rights reserved

  include_once('PatternSubject.php');
  include_once('PatternObserver.php');

  define('BR', '<'.'BR'.'>');

  echo 'BEGIN TESTING OBSERVER PATTERN'.BR;
  echo BR;

  $patternGossiper = new PatternSubject();
  $patternGossipFan = new PatternObserver();
  $patternGossiper->attach($patternGossipFan);

  $patternGossiper->updateFavorites(
     'abstract factory, decorator, visitor');

  $patternGossiper->updateFavorites(
     'abstract factory, observer, decorator');
  $patternGossiper->detach($patternGossipFan);

  $patternGossiper->updateFavorites(
    'abstract factory, observer, paisley');

  echo BR.BR;
  echo 'END TESTING OBSERVER PATTERN'.BR;


download source, use right-click and "Save Target As..." to save with a .php extension.

output of testObserver.php

BEGIN TESTING OBSERVER PATTERN



*IN PATTERN OBSERVER - NEW PATTERN GOSSIP ALERT* new favorite patterns: abstract factory, decorator, visitor *IN PATTERN OBSERVER - PATTERN GOSSIP ALERT OVER*

*IN PATTERN OBSERVER - NEW PATTERN GOSSIP ALERT* new favorite patterns: abstract factory, observer, decorator *IN PATTERN OBSERVER - PATTERN GOSSIP ALERT OVER*

END TESTING OBSERVER PATTERN

References

Design Patterns

Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides

PHP 5

The Official PHP web site
Core PHP Programming, 3rd Edition by Leon Atkinson and Zeev Suraski
Sign In
to add your own comment
Comment by prouty Rate this Comment

In class PatternSubject -> function detach(), the arguments in array_search are in the incorrect order. It should be:

$key = array_search($observer_in, $this->observers);

(needle first, then haystack)