Cargando la página...

Patrón Cadena de comando (Command Chain)

Publicado por Gastón el 28/03/2010 en PHP - Nivel Avanzado

Tabla de contenidos

Avatar de

La tabla de contenidos pertenece al artículo completo y no al contenido parcial de cada página del mismo si fuese el caso.

Leer los comentarios.

Resúmen

Necesitamos hacer simple la ejecución de comandos, sin importar de donde provengan.
Encapsulando en diferentes clases las diferentes funciones que queremos darle a nuestra aplicación.
Este artículo explica como implementar esto de una manera profesional.

Sobre el autor

Avatar de Gastón

Gastón tiene 30 años, vive en Argentina / Santa Fe / Santa Fe y su ocupación es Desarrollador de aplicaciones web.

Forma parte del club desde 19/10/2009 a las 20:52 habiendo estado en linea hace 2 días a las 00:18 por última vez.

Ha publicado 47 artículos en clubdesarrolladores con un promedio de valoración de 7.87 puntos. Puedes visitar su sitio web en http://www.devstudios.com.ar

Estadísticas

  • Leido 1419 veces
  • Valorado 2.00 puntos
Tenemos un sistema web que queremos hacer trabajar de diferente forma según un parámetro. Aqui por simplicidad se utiliza la línea de comandos, pero puede ser por ejemplo un parámetro dado por $_GET.
Este conjunto de clases se encargará, a partir de ese parámetro, de retornar la salida en el formato en que fue solicitada.

Interface Commandable



Se encarga de definir un metodo que será implementado por los diferentes comandos y será llamado en su debido momento.

interface commandable {
public function onCommand($name, $args);
}


Clase CommandChain



Es un contenedor de comandos, que además tiene un método para irlos ejecutando. Si el comando acepta la orden, entonces los demás comandos no serán invocados.
Este patrón básicamente, pregunta a los comandos si estos pueden aceptar la orden. Mientras no la acepten, se continúa intentando con los comandos que siguen.

class CommandChain {
private $commands = array();

public function addCommand(commandable $command) {
$this->commands[] = $command;
}

public function runCommand($name, $args) {
foreach($this->commands as $command) {
if($command->onCommand($name, $args)) {
return true;
}
}
return false;
}
}


Clase Abstracta Command



Esta clase es la base para los comandos, tiene métodos que simplifican la creación de nuevos comandos.
Es auto-explicativa.

abstract class Command implements commandable {
protected $command = null;
protected $caseInsensitive = true;

public function __construct() {
if(null === $this->command) {
throw new Exception ('Debe definir el comando');
}
}

public function onCommand($name, $args) {
if($this->compareCommandName($name)) {
return false;
}
$this->handleCommand($args);
return true;
}

private function compareCommandName($name) {
if($this->caseInsensitive) {
return strtolower($name) != strtolower($this->command);
}else {
return $name != $this->command;
}
}

abstract protected function handleCommand($args);
}


RSSCommand



Comando que retornaría RSS.

class RSSCommand extends Command {
protected $command = 'rss';

protected function handleCommand($args) {
//Do something...
echo get_class($this), PHP_EOL;
}
}


XMLCommand



Comando que retornaría XML.

class XMLCommand extends Command {
protected $command = 'xml';

protected function handleCommand($args) {
//Do something...
echo get_class($this), PHP_EOL;
}
}


JSONCommand



Comando que retornaría JSON.

class JSONCommand extends Command {
protected $command = 'json';

protected function handleCommand($args) {
//Do something...
echo get_class($this), PHP_EOL;
}
}


Dispatcher



Esta clase se encarga de cargar la lista de comandos disponibles, y mediante el método runCommand ejecuta los comandos correspondientes.
Si ningún comando acepta, entonces ejecuta el método propio handleCommand.

class Dispatcher extends CommandChain {
public function __construct() {
$this->addCommand(new RSSCommand());
$this->addCommand(new XMLCommand());
$this->addCommand(new JSONCommand());
$this->addCommand(new PanelCommand());
}

public function runCommand($name, $args) {
if(!parent::runCommand($name, $args)) {
return $this->handleCommand($args);
}
}

protected function handleCommand($args) {
echo get_class($this), PHP_EOL;
return true;
}
}


Modo de uso



Muy simple. Se crea la instancia del despachador y luego se corre pasandole el parámetro.

$dispatcher = new Dispatcher();
$dispatcher->runCommand($argv[1], null);


Patrón muy útil a la hora de diseñar un sistema grande. Este patrón hace que los mismos comandos indiquen si la acción es aceptada o no. Simplifica la lógica del despachador de manera enorme.
Cualquier duda usen los comentarios o el foro.

Saludos.

Si tiene alguna pregunta sobre éste artículo por favor deje un comentario y será respondido.

Descargas

No existen descargas asociadas

Comentarios

Sus comentarios son importantes.

Listado de comentarios

No hay comentarios para listar, si desea puede crear el primer comentario para este artículo.

Agregar un comentario

Debe estar identificado para agregar un comentario