Archive for the 'Standard PHP Library (SPL)' Category

PHP Observer Design Pattern: The SplObserver

splObserverThe Standard PHP Library

For those of you in the Boston PHP 200 Days of Coding Advanced group and for those of you who develop with design patterns, you may have noticed that I have not taken advantage of PHP’s Standard Library (SPL). In part that’s because I don’t think about it, and the other is that often I have other features for the interface I’d like to add that are not in the SPL version. Further, there are only a couple, the Iterator that Larry talks about in his book, and the Observer pattern that I’m going to discuss in this post and on April 22 at Microsoft’s NERD Center next to the MIT campus.

In an earlier post on the Observer design pattern I noted that in a future post, I’d take a look at the built-in SplObserver and SplSubject interfaces. So as promised, here it is.

The class diagram is slightly different than the original, and to indicate the built-in interfaces, the backgrounds are filled with a light tint indicating, there’s nothing for you to add. If you compare Figure 1 with the class diagram in the other Observer pattern post, you can see certain fundamental differences:

Figure 1: Observer Class diagram with SPL Interfaces

Figure 1: Observer Class diagram with SPL Interfaces

With no abstract classes as part of the interface, everything passed to the concrete Subject and Observer is going to have to be implemented. With the Subject, that means implementing the notify() method and not having some protected properties, but otherwise, there’s not a lot of differences in the structure of the SplObserver and the Observer (from scratch.)

One Message: Lots of Ways to Configure the Message

Some developers treat the Observer design pattern like a magazine subscription—one magazine; lots of subscribers. I suppose that’s a legitimate use of the Observer, but it’s very expensive. Each concrete observer must be instantiated as a unique object. While the Subject (or SplSubject) supplies the data; the observers generally create something with that data; not just look at it. So, I decided to make a simple translation simulator. A club (like any of the many PHP groups in the world) has announcements, but rather than using the Observer for sending out notifications to subscribers, I created Observers who translated the event message from English to their own language. The concrete observers are named for their languages. But to get going, play the example and download the PHP code:
PlayDownload

When you test play the app, you’ll see that the all of the checkboxes on the left are checked and the text box is filled in with an event. Likewise, the data and day inputs are set to April and 22. You can just click the “Send Announcement” button to see the results. If you change the event to something other than “200 Days of Code” the only change you’ll see is in the English version. The other ones are only a simulation of a translation except for the month—they are actually translated. The idea would be to use a translation Web service to do the actual translations.

Beginning with the implementation of the SplSubject (ClubEvents), you can see the three abstract methods have been implemented using the signature from the SplMethod interface. (Their abstract form is shown at the top as comments.)

< ?php
class ClubEvents implements SplSubject
{
    /*Built-in abstract methods
     *abstract public void attach ( SplObserver $observer )
     *abstract public void detach ( SplObserver $observer )
     *abstract public void notify ( void )
    */
    private $member;
    private $observerSet = array();
    private $content= array();
 
    //add observer
    public function attach(SplObserver $observer)
    {
        array_push($this->observerSet, $observer);
    }
 
    //remove observer
    public function detach(SplObserver $observer)
    { 
      foreach($this->observerSet as $keyNow => $valNow)
      {
        if ($valNow == $observer)
        { 
          unset($this->observerSet[$keyNow]);
        }
      }   
    }
 
    //Set event name, month and day
    public function setState(array $content)
    {
        $this->content = $content;
        $this->notify();
    }
 
    public function getState()
    {
        return $this->content;
    }
 
    //Notify "subscribers"
    public function notify()
    {
        foreach ($this->observerSet as $value)
        {
            $value->update($this);
        }
    }
}
?>

If you’re familiar with the first example of the Observer on this blog, you’ll see similarities in the concrete Subject. About the only significant difference is the fact that the notify() method is wholly implemented in the concrete class (ClubEvents) instead of the Subject abstract class. The information (or data) generated by the SplSubject comes from the Client and triggers the notify() methods by calling setState() method. So instead of looking at the Observers next, we’ll look at the Client.

The Client’s Unlikely Role

Note: A primary principle of design patterns is,

Program to the interfaces; not the implementations.

In discussing the single SplSubject implementation (ClubEvents) and the many SplObserver implementations, I’ll be referring to them by the interface name except in certain specific cases. However, the references are to any implementation of either since we must assume (correctly) that any implementation contains a certain set of methods established in the abstract parent classes built into the Standard PHP Library (SPL).
Continue reading ‘PHP Observer Design Pattern: The SplObserver’

Share