PHP Design Patterns

Tutorials and Examples of Design Patterns in PHP

Decorator Pattern

Suppose you have a number of classes in your codebase that retrieve data from various services. One of those classes is a Web Service client:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface ServiceClient
{
    function getData();
}

class MyWebServiceClient implements ServiceClient
{
    private $data;
    function MyWebServiceClient()
    {
        $client = new SoapClient("some.wsdl");
        $this->data = $client->getDataFunction();
    }
    function getData()
    {
        return $this->data;
    }
}

You are already using this in some places in your code, like so:

1
2
3
$client = new MyWebServiceClient();
// Later in your code, and possibly in multiple places
print $client->getData();

It has sometimes become necessary to convert special characters in the data to html entities. Also, you would like the option to wrap the entire output in a paragraph html tag. You cannot modify the output of the original classes as it would break the places in your code that do not need the new functionality.

Sure, you could just put options in the getData() function, but that can get messy as you add more and more options over time. Instead, check out the decorator pattern:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
abstract class ServiceClientDecorator implements ServiceClient
{
    protected $serviceClient;
    public function __construct(ServiceClient $serviceClient)
    {
        $this->serviceClient = $serviceClient;
    }
}

class HtmlEntitiesDecorator extends ServiceClientDecorator
{
    public function getData()
    {
        return htmlentities($this->serviceClient->getData());
    }
}

class ParagraphDecorator extends ServiceClientDecorator
{
    public function getData()
    {
        return '<p>'.$this->serviceClient->getData().'</p>';
    }
}

Now, when any of your classes that implement the ServiceClient interface need the functionality provided by one or both of these new decorators, adding it is very simple:

1
2
3
4
5
6
7
$client = new MyWebServiceClient();
// Add our decorators
$client = new HtmlEntititesDecorator($client);
$client = new ParagraphDecorator($client);

// Later in your code, and possibly in multiple places
print $client->getData();

Now, the code has printed the output of the MyWebServiceClient’s getData() function, but with <p>…</p> around it, and with the content’s special characters replaced with html entities.

One Response to Decorator Pattern

  1. thinsoldier says:

    Very easy to understand but I think some people may overlook the importance/usefulness of the decorator pattern since all you’re doing in the examples could be accomplished by just concatenating P and /P around the getData() wherever it is you were going to display it.

    I find the decorator pattern is best for when you have a lot of parts to the data that need a lot of manipulation of their values and a lot of html but not so much html that it warrants a full page/template/view.

    For example in my (poorly written) real estate site I have an object that represents a property for sale in the listings table of the DB. All 126 fields of the property record!

    When it’s time to show info about the property to a visitor I only need to show them about a dozen fields. But most of those fields need to be manipulated. I need to ucfirst() the property status text, convert the price to Euros/Pounds/USD/BSD, attach the http://www.site.com/listings/… onto the permalink text of the listing, convert 3.5 into “3 1/2 Bath”, convert the square feet values into Acres if they are over 1 acres in size and lots of other stuff. Also all these fields had to be wrapped in html tags and ids and css classes etc.

    At first I had all that stuff as part of the code that happens _before_ the data is saved to the database. Then other clients came along who wanted the same system (but different) and I realized a lot of those manipulations were only relevant to the site visitors. So then I put those instructions in the main class file as $listing->displayOverview() method.

    But then some more clients came along who wanted something other than the default set of info in the default format. Some clients wanted the category value to link to a search results page of everything in that category. Some wanted the neighbourhood value to do the same. Some didn’t want the category or neighbourhood value to be shown. Sure I could have just use css to hide the neighbourhood span but some high end clients don’t want anyone to know where their house is located so the neighbourhood/address values weren’t allowed to be anywhere in the markup. They had to be taken out at the code level.

    It unfortunately took a looong time and a lot of clients on this system to realize I needed to take this segment of my code and turn it into a custom decorator for each client that needed one.

    Before that realization, at one point I had a site identifier variable and a ton of IF statements strewn throughout the code that made it a nightmare to read!

    For another good example of decorator usage see this Zend Framework Zend_Form screencast (requires having a zend.com account): http://www.zend.com/en/webinar/Framework/webinar-leveraging-zend_form-decorators-20091216.flv

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>