Blog de Gonzalo

Decorator

El patrón de decorator nos permite añadir, quitar o modificar responsabilidades a un objeto dinámicamente, las funcionalidades se modifican/añadirán/retirarán durante la ejecución de la aplicación.
La gran ventaja es que nos permite extender objetos incluso en situaciones cuando la extensión por herencia no es viable o no es necesaria. Adicionalmente nos ayuda a conservar el principio de Abierto/Cerrado, en donde se dicta que cada entidad debe estar abierta a extensión pero cerrada a modificación.
Otra ventaja del decorator es que evitan crear clases complejas con mucho código, que en la mayoría de los casos no será evaluado. Nosotros podemos usar distintas combinaciones del decorator para generar distintos comportamientos o resultados.



//Interface coffe  
interface iCoffee
{
public function getBaseCost();
}
//Implementa getBaseCost
class Coffee implements iCoffee
{
protected $_baseCost = 0;
public function getBaseCost()
{
return $this->_baseCost;
}
}
//Hereda de coffe pq es otro tipo de café
class BlackCoffee extends Coffee
{
public function __construct()
{
$this->_baseCost = 5;
}
}
//Abstract cafe de los decorators
abstract class CoffeeDecorator implements iCoffee
{
protected $_coffee;
public function __construct(iCoffee $Coffee)
{
$this->_coffee = $Coffee;
}
}
class WithCream extends CoffeeDecorator
{
public function getBaseCost()
{
return $this->_coffee->getBaseCost() + 1.5;
}
}
class WithMilk extends CoffeeDecorator
{
public function getBaseCost()
{
return $this->_coffee->getBaseCost() + 4;
}
}
class WithChocolate extends CoffeeDecorator
{
public function getBaseCost()
{
return $this->_coffee->getBaseCost() + 5;
}
}
$coffee = new WithChocolate(new WithMilk(new WithCream(new BlackCoffee())));
echo 'El precio del cafe es: ' . $coffee->getBaseCost().'?';

Creo que éste es el ejemplo más sencillo de todos. Es fácil de entender.