Design Patterns in PHP - Decorator Pattern

Continuing my series on PHP design patterns, today it’s the turn of the Decorator.
By Sam Holman
7th December 2010
In contrast to last week’s Strategy Pattern which is used to change the “guts” of a class, the Decorator Pattern is used to extend the behavior of a class with different functionality at run time. This is achieved by implementing a “decorator” class that implements the same interface as the object that you wish to “decorate” and wraps it’s content.

The following illustrates a simple class that we may wish to decorate. It’s a very basic implementation of a Property class which implements a PropertyInterface. It has two simple get and set methods and nothing more:
PropertyInterface.inc.php
Property.inc.php
_value = $value;
        return true;
    }

    public function getValue()
    {
        return $this->_value;
    }
}
The above class would be fine for the most basic of properties, but what if we wanted something a little more complicated - perhaps code to validate the property on set or to transform it on get.
In each of these situations we could use a decorator to change the behaviour of the base property object. The following two classes (not including the abstract base class) could be used to transform a string property to uppercase or pad it to a particular length:
PropertyDecorator.inc.php
_property = $product;
    }

    public function setValue($value)
    {
        return $this->_property->setValue($value)
    }

    public function getValue()
    {
        return $this->_property->getValue();
    }
}
UppercasePropertyDecorator.inc.php
_property->getValue());
    }
}
PaddedPropertyDecorator.inc.php
_length = $length;
        }

        if (is_string($string)) {
            $this->_string = $string;
        }

        return parent::__construct($product);
    }

    public function getValue()
    {
        return str_pad($this->_property->getValue(), $this->_length, $this->_string);
    }
}
Because the decorators and the concrete Property objects all implement the same PropertyInterface and the decorators will accept any objects which also implement this interface, the decorators can be combined to make more complex decorations.
So here’s some examples of how we can use these decorators:
example.php
setValue('property value');

echo $property->getValue(); //Outputs: property value

$decoratedProperty = new UppercasePropertyDecorator($property);

echo $decoratedProperty->getValue(); //Outputs: PROPERTY VALUE

$paddedUpperProperty = new PaddedPropertyDecorator($decoratedProperty, 20, '*');

echo $paddedUpperProperty>getValue(); //Outputs: PROPERTY VALUE******

echo $property->getValue(); //Outputs: property value
The decorator pattern is basically a substitute for sub-classing, and should be used if the behavior may need to be added and removed at run time or if there is a need to combine the functionality of multiple decorators.
I hope this has helped you to better understand the implementation and possible uses for the Decorator Pattern.
As always, let me know your thoughts on this article @labelmedia on twitter. Bye for now!

Like this? Sign up to our newsletter for more!

Comments

matason 29th November 2012
Thanks Tom, this is a good, clean and clear example of the decorator pattern in action, very helpful!
Ashour 26th February 2013
Simple, concise, I read it and got back to work in 5min knowing how to basically implement a decorator. Great work. Thank you.

Add your own comment

© 2014 Label Media
We are recruiting