In our ongoing series about design patterns, we introduce the Decorator Pattern. The decorator pattern serves to add specific functionality to an existing class. The classic example of this is in GUI programming, when a widget needs a border, or graphic surrounding it. Not using the Decorator Pattern, one might just subclass out the widget class and add a border to the subclassed widget. This becomes more difficult however, when there are multiple classes of widgets. This becomes almost impossible when dealing with a collection of widgets.
So, enter the Decorator Pattern.
The easiest way to realize the decorator pattern, is simply to pass the decorated class to the decorator’s constructor function, then expose whatever functions of the decorated class you desire, adding functionality as necessary. So, here’s an example of a widget class (the decorated), that get’s decorated by the decorator:
class Widget { /** * property to hold the data for the widget * @var array $_data */ private $_data = array(); /** * function to draw a widget from the existing data */ public function draw ( ) { // CREATE a local variable to represent the result $markup = ''; // ITERATE through each of the key/value pairs in the _data property ... foreach ($this->_data as $key => $value) { // APPEND the key/value pair to the markup variable $markup .= " <dt>{$key}</dt> <dd>{$value}</dd> "; } // RETURN the result, wrapped in a dl tag return " <dl>{$markup}</dl> "; } // END draw } // END Widget class WidgetDecorator { /** * property to hold the item that will be decorated */ private $_decoratedObject; /** * Constructor * @param object $DecoratedObject */ public function __construct ($DecoratedObject) { // SET the _decoratedObject property to the object that was provided $this->_decoratedObject = $DecoratedObject; } // END __construct /** * function to expose the draw method of the _decoratedObject */ public function draw ( ) { // RETURN the result of the _decoratedObject's draw method, wrapped in a div return ' <div class="decorated">' . $this->_decoratedObject->draw() . '</div> '; } // END draw } // END WidgetDecorator
While it’s common to talk about GUI implementations of the Decorator Pattern, there are several other implementations that fit the Decorator Pattern idea. You might need to wrap an event logger, that already logs events to one log, with a user notifying system that also notifies users. You might need to do all kinds of things.
The idea here, is that any time you need specific functionality added to a class (or set thereof), you might consider the Decorator Pattern.
Related posts:
- Observer Pattern One of my favorite design patterns, is theĀ Observer Pattern. TheĀ Observer...
- Factory Pattern In following the theme of design patterns we’re starting this...
- Singleton Pattern One of the things I see all the time with...
Tags: code, design pattern, Development, ood, oop, PHP