Design pattern in PHP: Decorator Pattern

In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, dynamically, without affecting the behavior of other objects from the same class.

What problems can it solve?

In general, we often use inheritance to extend a class. As the function and class increase more and more, when you try to apply similar modifications to different branches of your inheritance tree, you are likely to write duplication code. Below is an example showing the problem of inheritance:

<?php
/**
 * component parent class
 */
abstract class Sharp
{
	// define a function
	abstract public function looked();
}

/**
 * a component subclass
 */
class Circle extends Sharp
{
	public function looked()
	{
		echo 'circle: ';
	}
}

/**
 * anthor component subclass
 */
class Rectangle extends Sharp
{
	public function looked()
	{
		echo 'rectangle: ';
	}
}


// now what do we do when we want red and strong-border circle using inheritance
class RedColorAndStrongBorderCircle extends circle
{
	public function looked()
	{
		echo parent::looked() . ' redColor strong-border';
	}
}

If we want more color sharp, what do we do? It’s horrible, right?

What decorator pattern can do?

Without changing the original class, we can add some extra duties to an object dynamically using delegation and composition.

Implementation

Below is an example how decorator pattern in PHP works. We can make a lot of different sharps with variable decorator:

Step 1: Create a sharp abstract class

/**
 * component parent class
 */
abstract class Sharp
{
	// define a function
	abstract public function looked();
}

Step 2: Create specific sharp component

/**
 * a component subclass
 */
class Circle extends Sharp
{
	public function looked()
	{
		echo 'circle: ';
	}
}

/**
 * anothor component subclass
 */
class Rectangle extends Sharp
{
	public function looked()
	{
		echo 'rectangle: ';
	}
}

Step 3: Create decorator class which also extends sharp abstract class and wrap a component as its property

/**
 * decorator parent class
 * it extends the Sharp class too
 */
abstract class SharpDecorator extends Sharp
{
	protected $sharp;

	public function __construct(Sharp $sharp)
	{
		$this->sharp = $sharp;
	}
}

Step4: Create specific decorator subclass

/**
 * a redcolor class to decorator sharp class
 */
class RedColor extends SharpDecorator
{
	public function looked()
	{
		echo $this->sharp->looked() . ' redColor ';
	}
}

/**
 * a strongborder class to decorator sharp class
 */
class StrongBorder extends SharpDecorator
{
	public function looked()
	{
		echo $this->sharp->looked() . ' strong-border ';
	}
}

Step 5: create some decoratored sharp

// a red strong circle
$circle = new StrongBorder(new RedColor(new Circle));
$circle->looked();

echo "\n";

// a strong rectangle
$rectangle = new StrongBorder(new Rectangle);
$rectangle->looked();

Step 6: run the script and check the result

$ php decorator.php
circle:  redColor  strong-border
rectangle:  strong-border

Pros of decorator pattern

  1. It’s more flexible compared to inheritance
  2. There is no need to change original class
  3. With lots of decorators, we can build very flexible structures at runtime dynamically

Cons of decorator pattern

  1. As the decorator increase, it makes our application more complicated
  2. It gets more difficult when we debug our application when something wrong because of the very flexible structures

RSS