Siguiendo la serie de codekatas sobre patrones de diseño del software llegamos a un patrón para añadir funcionalidades a un código ya existente a base de objetos llamados decoradores. Este post trata de lo que se llama el patrón Decorador/Decorator en inglés.
Se puede usar para decorar transacciones económicas, líneas de teléfono, clientes, etc.. es decir, se puede aplicar a muchos conceptos. Pero vamos a suponer que estamos pintando por pantalla coches, tendremos un coche básico, y queremos decorarlo. Al grano, que es más fácil ver el código que explicarlo..
En qué consiste el patrón decorador
En líneas generales consiste en hacer, con los conceptos que corresponda, una estructura como la siguiente:
Se trata de extender añadiendo funcionalidades al objeto sin tocarlo. Es decir, tenemos una clase ya implementada con unas características. Y añadimos otros objetos, sin duplicar código, que sólo añaden, decorando, al objeto inicial y sin tocarlo.
Cómo se programa
Según cada lenguaje de programación cambiará su sintaxis, en PHP podría ser algo como lo siguiente. Primero una definición de contrato de uso, que define por ejemplo que tiene que haber una función de pintado por pantalla del coche:
<?php
interface ICar
{
public function draw();
}
..la implementación del coche genérico:
<?php
class Car implements ICar
{
public function draw()
{
/*
* Here goes the code for drawing the basic of the car.
*/
}
}
..la implementación del decorador general:
<?php
class CarDecorator implements ICar
{
private $car;
public function __construct(Car $car)
{
$this->car = $car;
}
public function draw()
{
$this->car->draw();
}
}
..un decorador de coche que añade al pintado del coche genérico, el pintado de un alerón:
<?php
class SpoilerDecorator extends CarDecorator
{
public function __construct(Car $car)
{
parent::__construct($car);
}
public function draw()
{
parent::draw();
/*
* Here the code that draws the spoiler..
*/
}
}
..otro decorador de coche, que añade al genérico, el pintado de las llantas:
<?php
class RimsDecorator extends CarDecorator
{
public function __construct(Car $car)
{
parent::__construct($car);
}
public function draw()
{
parent::draw();
/*
* Here the code that draws the rims..
*/
}
}
Quedaría el poder acumular los decoradores en un mismo coche, ya que con este esquema sólo permitiría aplicar un decorador.
Es decir, si combinamos este patrón con otros, podríamos aplicar múltiples decoradores a un mismo coche, teniendo por ejemplo en este caso, un coche básico con ambas cosas, alerón y llantas.