An Introduction to Using the Decorator Pattern with PHP

A decorator class allows you to add more capacity to an existing class while leaving the original class untouched. It has certain advantages over inheritance, as you will learn in this first article of a three-part series.

Introduction

Among the plethoric variety of design patterns that can be applied in software engineering, there are a few that are specifically interesting for web developers. These feature potentially easy implementation and versatility, particularly when working with object-oriented applications. Speaking more specifically, the Decorator pattern is one that I found myself using quite frequently inside my PHP-driven applications, in cases where I needed to construct a “bridging” class that was capable of extending the operability and functionality of a base class, but without having to introduce changes in its original structure.

Does that sound a little bit complex? Well, fear not; let me point you in the right direction. A “decorator” class is one that allows you to add more capacity to an existing class, by using some intermediate methods, while leaving the original class untouched. Okay, you have every right to say that the same result can be achieved by using inheritance, and then creating some cool subclasses. However, in that case you’d be working with objects of the same type, while a “decorator” object belongs to a completely different family. Are you getting my point now? I bet you are.

Indeed, one of the most appealing aspects of the decorator design pattern is the ease with which you can use a class of different type to extend the capabilities of another. Of course, this isn’t always the best course of action to take, simply because it can be much easier to modify the original class by using inheritance, but there are situations where a decorator class can find its place inside an application.

Due to the wide range of web applications where the decorator pattern can be successfully applied, over the course of this series, I’ll show you some useful pointers to demonstrate how this pattern works, and how it can be introduced in your own PHP applications with only minor hassles. Before you start reading the rest of this article, make sure that you have a pretty good understanding of object-based programming with PHP, since you’ll see an abundance of material related to this topic.

Having introduced the basics of the decorator pattern, let’s learn how it can be applied to PHP with several practical examples. Let’s get started!

{mospagebreak title=Creating a base class}

As usual, a good point to start explaining how the decorator pattern works with PHP is simply by coding an easy-to-grasp example, thus you can understand from the very beginning the way this pattern can be applied inside a Web application.

Considering the concepts that I deployed before, first I’ll code a sample PHP class, which will be used as a base structure. Then I’ll create a decorator class which will extend the functionality of the base class. Therefore, here is the definition of the core class, which I called “StringSaver.” Please take a look at its source code:

// define ‘StringSaver’ class (this base class will be decorated
later on)
class StringSaver{
    private $path;
    private $str;
    public function __construct($path,$str){
        $this->path=$path;
        $this->str=$str;
    }
    public function save(){
        if(!$fp=fopen($this->path,’w’)){
            throw new Exception(‘Error opening string file’);
        }
        fwrite($fp,$str);
        flose($fp);
    }
    public function getPath(){
        return $this->path;
    }
    public function getString(){
        return $this->str;
    }
}

Even when the above class looks rather primitive, its functionality is indeed easy to understand. As you can see, this class performs a simple task, which merely consists of saving an input string to a given text file, previously passed as a parameter to the constructor.

Also, aside from exposing the respective “save()” method, the class has two additional ones. These are “getPath()” and “getString()” respectively, and they are responsible for returning the two properties previously assigned inside the constructor, that is $path and $str.

So far, as you’ll agree with me, the previous class certainly can’t be considered anything special. However, suppose that you want to extend its functionality without modifying its original structure, and also without creating a sub class from it. How can this be done? Well, here is where the decorator pattern comes in, since it’s possible to define a decorator class which can extend the operability of the base class, meeting all the requirements that I mentioned before.

Therefore, in the next section, I’ll show you how to create a decorator class that can dd more functionality to the previous “StringSaver” class. Thus, if you wish to learn how this will be achieved, go ahead and keep reading.

{mospagebreak title=Defining the structure of a Decorator object}

As you learned in the previous section, once the base “StringSaver” class has been defined, creating a decorator class is indeed a straightforward task to perform. Now, with reference to extending the existing functionality of the “StringSaver” class, suppose that you want to manipulate its $str property, in many creative and clever ways (I’m just kidding), such as uppercasing and lowercasing it. Sounds pretty cool, right?

Okay, in order to do that, I’m going to define a decorator class which will take the $str property of the base class and assign it as its own property. In this way it will act like a programmatic bridge for further decorators.

As usual, theory should be supported by the corresponding hands-on examples, so below is the definition of the “StringDecorator” class. Please examine its signature:

class StringDecorator{
    protected $strsaver;
    public $str;
    // pass ‘StringSaver’ object to constructor
    public function __construct(StringSaver $strsaver){
        $this->strsaver=$strsaver;
        // retrieve string from original ‘StringSaver’ object
        $this->resetString();
    }
    // obtain string from ‘StringSaver’ object
    // thus the original property remains the same
    public function resetString(){
        $this->str=$this->strsaver->getString();
    }
    // return string to calling code
    public function displayString(){
        return $this->str;
    }
}

If you take a look at the above class, then you’ll realize that there are some interesting things worth noting. First, the “StringDecorator” class accepts an object of type “StringSaver” as its unique parameter, which is assigned as a class property inside the constructor.

However, the most relevant thing happens in relation with the “resetString()” method, since it uses the “getString()” method that belongs to the “StringSaver” class and obtains its $str property. While this is a simple concept, it demonstrates how to build a class that takes up the properties of a base class without modifying its original structure. Now, do you see how a decorator class fits into the whole picture?

All right, at this point, the “StringDecorator” class is limited to taking the $str property from the base class, but aside from that, it’s not doing anything else. Therefore, it’s time to leap forward and see how the original $str property can be uppercased and lowercased by deriving a couple of concrete subclasses from the “StringDecorator” class.

That’s exactly the subject of the next section, so I recommend you jump straight into it and keep learning more.

{mospagebreak title=Creating additional decorator classes}

As you learned in the previous section, once the “StringDecorator” class has been properly defined, extending the functionality of the base “StringSaver” class that you saw before is a breeze. All I have to do is derive a pair of simple subclasses from the “StringDecorator” class and the work is almost done.

That said, here are the corresponding definitions for the decorator subclasses, tasked with lowercasing and uppercasing the $str property of the respective base class, but without changing its original structure:

// define ‘StringUppercaser’ class (decorates ‘StringSaver’ class)
class StringUppercaseDecorator extends StringDecorator{
    private $strDecorator;
    // pass ‘StringDecorator’ object to constructor
    public function __construct(StringDecorator $strDecorator){
        $this->strDecorator=$strDecorator;
    }
    // convert string to uppercase
    public function uppercaseString(){
        $this->strDecorator->str=strtoupper($this->strDecorator-
>str);
    }
}
// define ‘StringLowercaser’ class (decorates ‘StringSaver’ class)
class StringLowercaseDecorator extends StringDecorator{
    private $strDecorator;
    // pass ‘StringDecorator’ object to constructor
    public function __construct(StringDecorator $strDecorator){
        $this->strDecorator=$strDecorator;
    }
    // convert string to lowercase
    public function lowercaseString(){
        $this->strDecorator->str=strtolower($this->strDecorator-
>str);
    }
}

As you can see, the two classes listed above are in fact subclasses of “StringDecorator,” and accept this object as the only input parameter. The reason for doing this should now be obvious, since both child classes use their “uppercaseString()” and “lowecaseString()” methods respectively to modify the $str property, while maintaining the structure of the base class clearly untouched.

The following method definitions demonstrate the concepts that I explained previously:

// convert string to uppercase
public function uppercaseString(){
    $this->strDecorator->str=strtoupper($this->strDecorator-
>str);
}
// convert string to lowercase
public function lowercaseString(){
    $this->strDecorator->str=strtolower($this->strDecorator-
>str);
}

Now you should be able to understand how a decorator class works to expand the capacity of a specific class, without modifying its original definition. Nevertheless, I’d like to show you how all the previous sample classes fit with each other, therefore I’ve set up a demonstrative example below. Have a look, please:

// instantiate ‘StringSaver’ object
$strSaver=new StringSaver(‘strings/strings.txt’,’This is a sample
string’);
// instantiate ‘StringDecorator’ object
$strDecorator=new StringDecorator($strSaver);
// instantiate ‘StringUppercaseDecorator’ object
$strupperDecorator=new StringUppercaseDecorator($strDecorator);
// instantiate ‘StringLowercaseDecorator’ object
$strlowerDecorator=new StringLowercaseDecorator($strDecorator);
echo ‘Original string is as follows: ‘.$strDecorator-
>displayString().'<br />';
// convert string to uppercase
$strupperDecorator->uppercaseString();
echo ‘String after using ‘StringUppercaseDecorator’ object is
as follows: ‘.$strDecorator->displayString().'<br />';
// convert string to lowercase
$strlowerDecorator->lowercaseString();
echo ‘String after using ‘StringLowercaseDecorator’ object is
as follows: ‘.$strDecorator->displayString().'<br />';

The above code snippet shows how the respective decorator classes can be used, in order to uppercase and lowercase a given string, which has been passed as an argument to the original “StringSaver” class.

Not surprisingly, the output of the previous script is the following:

Original string is as follows: This is a sample string

String after using ‘StringUppercaseDecorator’ object is as follows: THIS IS A SAMPLE STRING

String after using ‘StringLowercaseDecorator’ object is as follows: this is a sample string

All right, I believe the examples shown above demonstrate in an easy way how the decorator pattern works. However, l will go one step further with reference to this example and create an additional decorator class, which will be capable of reversing the original input string. Here is the definition for this brand new decorator class:

// define ‘StringReverser’ class (decorates ‘StringSaver’ class)
class StringReverseDecorator extends StringDecorator{
    private $strDecorator;
    // pass ‘StringDecorator’ object to constructor
    public function __construct(StringDecorator $strDecorator){
        $this->strDecorator=$strDecorator;
    }
    // reverse string
    public function reverseString(){
        $this->strDecorator->str=strrev($this->strDecorator-
>str);
    }
}

If you examine the class listed above, you’ll realize that it implements the same approach that you learned with the previous decorator classes. Of course, the only difference rests on the fact that the corresponding $str property is reversed via the “reverseString()” method:

public function reverseString(){
    $this->strDecorator->str=strrev($this->strDecorator->str);
} 

Now that you know how this newly created class does its business,  take a look at how it can be used in conjunction with the other decorator classes:

// instantiate ‘StringSaver’ object
$strSaver=new StringSaver(‘strings/strings.txt’,’This is a sample
string’);
// instantiate ‘StringDecorator’ object
$strDecorator=new StringDecorator($strSaver);
// instantiate ‘StringUppercaseDecorator’ object
$strupperDecorator=new StringUppercaseDecorator($strDecorator);
// instantiate ‘StringLowercaseDecorator’ object
$strlowerDecorator=new StringLowercaseDecorator($strDecorator);
// instantiate ‘StringReverseDecorator’ object
$strrevDecorator=new StringReverseDecorator($strDecorator);
echo ‘Original string is as follows: ‘.$strDecorator->displayString().'<br />';
// convert string to uppercase
$strupperDecorator->uppercaseString();
echo ‘String after using ‘StringUppercaseDecorator’ object is
as follows: ‘.$strDecorator->displayString().'<br />';
// convert string to lowercase
$strlowerDecorator->lowercaseString();
echo ‘String after using ‘StringLowercaseDecorator’ object is
as follows: ‘.$strDecorator->displayString().'<br />';
// reverser string
$strrevDecorator->reverseString();
echo ‘String after using ‘StringReverseDecorator’ object is as
follows: ‘.$strDecorator->displayString().'<br />';
// convert string to uppercase
$strupperDecorator->uppercaseString();
echo ‘String after using ‘StringUppercaseDecorator’ object is
as follows: ‘.$strDecorator->displayString().'<br />';

And finally, the results outputted by the previous script would be as follows:

Original string is as follows: This is a sample string

String after using ‘StringUppercaseDecorator’ object is as follows: THIS IS A SAMPLE STRING

String after using ‘StringLowercaseDecorator’ object is as follows: this is a sample string

String after using ‘StringReverseDecorator’ object is as follows: gnirts elpmas a si siht

String after using ‘StringUppercaseDecorator’ object is as follows: GNIRTS ELPMAS A SI SIHT

Try creating different decorator classes and see what happens in each case. The experience is really educational. Believe me, you won’t be disappointed!

Final thoughts

In this first article of the series, you learned the basics of how to apply the decorator pattern in PHP. Although the sample classes that I coded here were quite simple, they allowed me illustrate by an easy fashion the way this pattern can be used.

However, my journey has not finished yet. In the next tutorial, I’ll explain how to use the decorator pattern in a group of classes that handle MySQL result sets, in this way bringing this pattern to a real-world application. If you wish to find out how this will be done, don’t miss the next tutorial!

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan