Friends

Quick Guide : Design Patterns for PHP - part III

The observer pattern
why?
To define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
One object makes itself observable by adding a method that allows another object, the observer, to register itself. When the observable object changes, it sends a message to the registered observers.

The participants classes in this pattern are:
Observable - interface or abstract class defining the operations for attaching and de-attaching observers to the client. 
ConcreteObservable - concrete Observable class. It maintain the state of the object and when a change in the state occurs it notifies the attached Observers.
Observer - interface or abstract class defining the operations to be used to notify this object.

A simple example is a list of users in a system. The code in Listing 4 shows a user list that sends out a message when users are added. This list is watched by a logging observer that puts out a message when a user is added.
Listing 4. Observer.php

<?php
interface IObserver
{
  function onChanged( $sender, $args );
}

interface IObservable
{
  function addObserver( $observer );
}

class UserList implements IObservable
{
  private $_observers = array();

  public function addCustomer( $name )
  {
    foreach( $this->_observers as $obs )
      $obs->onChanged( $this, $name );
  }

  public function addObserver( $observer )
  {
    $this->_observers []= $observer;
  }
}

class UserListLogger implements IObserver
{
  public function onChanged( $sender, $args )
  {
    echo( "'$args' added to user list\n" );
  }
}

$ul = new UserList();
$ul->addObserver( new UserListLogger() );
$ul->addCustomer( "Jack" );
?>


Output:

% php observer.php 
'Jack' added to user list
%

This code defines four elements: two interfaces and two classes. The IObservable interface defines an object that can be observed, and the UserList implements that interface to register itself as observable. The IObserver list defines what it takes to be an observer, and the UserListLogger implements that IObserver interface. This is shown in the UML in Figure 4.

Figure 4. The observable user list and the user list event logger
The observable user list and the user list event logger


The test code creates a UserList and adds the UserListLogger observer to it. Then the code adds a customer, and the UserListLogger is notified of that change.
It's critical to realize that the UserList doesn't know what the logger is going to do. There could be one or more listeners that do other things



In next post I will explain the forth design pattern "The chain-of-command pattern".



0 comments:

Twitter Delicious Facebook Digg Stumbleupon Favorites More