Archive for the 'Hollywood Principle' Category

PHP Template Method Pattern: Geolocation Encapsulated

bostonI was invited to speak at on April 22 at Microsoft’s NERD Center in Boston for Month 4 of Boston PHP’s 200 Days of Code. The Advanced track of 200 Days of Coding is going through Larry Ullman’s book, PHP Advanced & OO Programming (3rd ed), and I’ll be talking about materials from Chapters 8-10. However, with a little over an hour, I am using Occam’s razor to keep things focused, pertinent and related to the relevant chapters. Chapter 10 is about Networking with PHP, and by way of preview, I thought I’d take the material that Larry has on geolocation, and put it into an OOP structure using the Template Method design pattern. I also made a number of other modifications for which Larry cannot be blamed! Go ahead and Play the program to see what it does and Download the code. (The text window defaults to sandlight.com but you can add any URL you want.)
PlayDownload

The Magical Template Method

The first thing I did was to set up the geolocation app with a Template Method. You can see previous discussions and examples of the Template Method on this blog, but I wanted to include the class diagram the Gang of Four used to see how simple but elegant this pattern actually is. Figure 1 shows this subtle but powerful method:

Figure 1: Template Method class diagram

Figure 1: Template Method class diagram

The nice thing about this design pattern is that it has lots of uses as you may have already seen on this blog. However, the same simple principle is used: Abstract methods from an abstract class are implemented in a concrete method from the same abstract class. What the Template Method does is to provide a blueprint for the order of the methods to be used with the exact content dependent on the intended use.

So, starting with the abstract class, you can see how this implementation works:

< ?php
abstract class ILocatorTemplate
{
    protected $url, $info, $data, $ip, $loc;
    protected $package=array();
    protected abstract function getLocation();
    protected abstract function bundle();
 
    //The Template Method
    protected function templateMethod()
    {
        $this->getLocation();
        $this->bundle();
    }
}
?>

A number of protected properties are first declared, including an array object, $package. Next the two primitive operations are declared, getLocation() and bundle(). The former is for getting the geolocation of a URL and the second for placing that information into the $package object. That’s it! All that’s left to do is to implement the abstract class.

The Locator class

The concrete implementation of the ILocatorTemplate adds content to the properties and concrete operations to the two abstract methods.

< ?php 
class Locator extends ILocatorTemplate
{
    public function doLocate($place)
    {
        $this->loc = $place;
        $this->templateMethod();
        return $this->package;
    }
 
    protected function getLocation()
    { 
        $this->ip = gethostbyname($this->loc);
        $this->url = 'http://freegeoip.net/csv/' . $this->ip;
 
        $this->info = fopen($this->url, 'r');
        $this->data = fgetcsv($this->info);
        fclose($this->info);
    }
 
    protected function bundle()
    {
        $this->package['IP']=$this->data[0];
        $this->package['CountryID']=$this->data[1];
        $this->package['Country']=$this->data[2];
        $this->package['StateID']=$this->data[3];
        $this->package['State']=$this->data[4];
        $this->package['City']=$this->data[5];
        $this->package['Zip']=$this->data[6];
        $this->package['latitude']=$this->data[7];
        $this->package['longitude']=$this->data[8];
    }
}
?>

The doLocate() method holds the URL passed by the user. That is placed into one of the properties declared in the abstract class, $loc. Next, the $templateMethod() fires and it, in turn, launches first the getLocation() method and then the bundle() method. It doesn’t matter what is in those methods because they were defined abstractly. Therefore, any abstract method defined as part of template method will launch regardless of its implementation, as long as it adheres to the signature form in the abstract class. The getLocation() method pretty much follows the steps Larry lays out in Chapter 10. It uses the freegeoip.net Web service which returns CSV data with the location information.

The bundle() method transfers the data from the $data array send by the Web service into an associative array, $package. The keys in the associative array will serve as labels for the data once processed in the Client class.

The last step in the process is to return the $package containing an associative array with descriptive keys and location information. That’s it….but there is one more thing before we turn to the UI and client.

The Hollywood Principle

The Template Method exemplifies a larger design pattern principle called the Hollywood Principle, simply stated,

Don’t call us. We’ll call you.

It refers to how a parent class (ILocatorTemplate) call the operations of a subclass (Locator) and not the other way around. The templateMethod() function is a concrete method from the parent class, and both the getLocation() and bundle() methods are implementations of the child class, Locator. So, the parent class method calls the child class implementations; not vice versa. This fundamental principle will help keep your PHP OOP from getting tangled up.
Continue reading ‘PHP Template Method Pattern: Geolocation Encapsulated’