Este post es sobre el patrón de diseño del software llamado Chain of Responsability o Cadena de Responsabilidad. Se usa cuando se quieren tener varios objetos relacionados de forma que cada uno pueda hacer una cosa con una misma petición, o puede que sólo algunos tengan que hacer algo con dicha petición.
Se puede implementar enlazando los objetos entre sí para establecer una cadena, o utilizando el patrón Composite.
Al grano, una implementación del patrón enlazando los objetos entre sí
Simplemente consiste en este esquema de clases y métodos. La otra implementación sería usando Composite, pero por distinguir la técnica, tenemos entonces:
Los patrones de diseño del software son agnósticos a los lenguajes de programación. Una implementación entonces en PHP quedaría así. El Main.php:
<?php
require_once 'IEntity.php';
require_once 'Entity1.php';
require_once 'Entity2.php';
require_once 'Entity3.php';
echo 'Entity1'.PHP_EOL;
$entity1 = new Entity1();
$entity1->doTheJob();
echo 'Entity1 => Entity2'.PHP_EOL;
$entity2 = new Entity2();
$entity1->setNext($entity2);
$entity1->doTheJob();
echo 'Entity1 => Entity2 => Entity3'.PHP_EOL;
$entity3 = new Entity2();
$entity2->setNext($entity3);
$entity1->doTheJob();
La declaración de la interfaz que establece el contrato de uso:
<?php
interface IEntity {
public function setNext(IEntity $entity);
public function doTheJob();
}
Y las tres implementaciones:
<?php
class Entity1 implements IEntity
{
private $_next;
public function setNext(IEntity $entity)
{
$this->_next = $entity;
}
public function doTheJob()
{
echo 'Doing the job!'.PHP_EOL;
if (!empty($this->_next)) {
$this->_next->doTheJob();
}
}
}
<?php
class Entity2 implements IEntity
{
private $_next;
public function setNext(IEntity $entity)
{
$this->_next = $entity;
}
public function doTheJob()
{
echo 'Doing the job!'.PHP_EOL;
if (!empty($this->_next)) {
$this->_next->doTheJob();
}
}
}
<?php
class Entity3 implements IEntity
{
private $_next;
public function setNext(IEntity $entity)
{
$this->_next = $entity;
}
public function doTheJob()
{
echo 'Doing the job!'.PHP_EOL;
if (!empty($this->_next)) {
$this->_next->doTheJob();
}
}
}
Una ejecución del programa principal podría verse tal que así: