Monday, June 27, 2011

Decorator Design Pattern example using PHP

Decorator Design Pattern is a structural Pattern and also known as wrapper. The Decorator Pattern is used for adding additional functionality to a particular object during run-time. It is easy to add functionality to an entire class of objects by sub-classing an object during design time, but it adds extra codes as overhead.

With the Decorator Pattern, you can add functionality to a single object and leave others like it unmodified. Building all your functionality into an inheritance structure can result in an explosion of classes in a system. Even worse, as you try to apply similar modifications to different branches of your inheritance tree, you are likely to see duplication emerge.

Decorator answers “How can you structure your code to easily add conditional or rarely used features without putting the extra code directly in your class?”

Example using Decorator Design Pattern:
<?php

    abstract class Tile {
        abstract function getWealthFactor();
    }
   
    class Plains extends Tile {
        private $wealthfactor = 2;
        function getWealthFactor() {
            return $this->wealthfactor;
        }
    }
   
    // Decorator implementing the following
    abstract class TileDecorator extends Tile {
        protected $tile;
        function __construct( Tile $tile ) {
            $this->tile = $tile;   
        }
    }
   
    class DiamondDecorator extends TileDecorator {
        function getWealthFactor() {
            return $this->tile->getWealthFactor()+2;
        }
    }
   
    class PollutionDecorator extends TileDecorator {
        function getWealthFactor() {
            return $this->tile->getWealthFactor()-4;
        }
    }
   
    $tile = new Plains();
    print $tile->getWealthFactor(); // 2
    // Plains is a component. It simply returns 2
   
    $tile = new DiamondDecorator( new Plains() );
    print $tile->getWealthFactor(); // 4
    // DiamondDecorator has a reference to a Plains object. It invokes
    // getWealthFactor() before adding its own weighting of 2
   
    $tile = new PollutionDecorator( new DiamondDecorator( new Plains() ));
    print $tile->getWealthFactor(); // 0
    // PollutionDecorator has a reference to a DiamondDecorator object which
    // has its own Tile reference.

?>

Example without Decorator Design Pattern:
<?php

    abstract class Tile {
        abstract function getWealthFactor();
    }
   
    class Plains extends Tile {
        private $wealthfactor = 2;
        function getWealthFactor() {
            return $this->wealthfactor;
        }
    }
   
    class DiamondPlains extends Plains {
        function getWealthFactor() {
            return parent::getWealthFactor() + 2;
        }
    }
   
    class PollutedPlains extends Plains {
        function getWealthFactor() {
            return parent::getWealthFactor() - 4;
        }
    }
   
    $tile = new PollutedPlains();
    print $tile->getWealthFactor();
?>

Source:  From lecture notes of Design and Development Open Multi-tier Application