Implementing Observer
The observer pattern is the most complicated to implement of those
we'll look at, mainly because it requires a subject class, an
observer class, and several methods between them to regulate their
interaction.
We'll look at the subject object first. These objects need an
attach() method, and a way of notifying observing objects of a
state change - we'll call it notifyAll(). For completeness, we'll
also include a detach() method. Here is the implementation from
PEAR's Log:: package:
<?php /** * Adds a Log_observer instance to the list of observers that are be * notified when a message is logged. * * @param object Log_observer &$logObserver The Log_observer instance to * be added to the $listeners * array. * @access public */ function attach(&$logObserver) { if (!is_object($logObserver)) { return false; } $logObserver->_listenerID = uniqid(rand()); $this->_listeners[$logObserver->_listenerID] = &$logObserver; }
/** * Removes a Log_observer instance from the list of observers. * * @param object Log_observer $logObserver The Log_observer instance to * be removed from the $listeners * array. * @access public */ function detach($logObserver) { if (isset($this->_listeners[$logObserver->_listenerID])) { unset($this->_listeners[$logObserver->_listenerID]); } }
/** * Sends any Log_observer objects listening to this Log the message that * was just logged. * * @param array $msgObj The data structure holding all relevant log * information - the message, the priority, what * log this is, etc. */ function notifyAll($msgObj) { reset($this->_listeners); foreach ($this->_listeners as $listener) { if ($msgObj['priority'] <= $listener->priority) { $listener->notify($msgObj); } } }
Since we can't use an object as an array index, we create a unique
index when every observer is attached so that we can track them
and detach() them transparently to the end user.
The observer side is simpler; we just need to implement the
notify() method that we called from the subject in notifyAll()
above. We can do whatever we like in it:
<?php /** * This is a stub method to make sure that Log_observer classes do * something when they are notified of a message. The default * behavior is to just print the message, which is obviously not * desireable in practically any situation - which is why you need * to override this method. :) * * @param array $messageOb A hash containing all information - the text * message itself, the priority, what log it came * from, etc. */ function notify($messageOb) { print_r($messageOb); }
|