Comando

RECU-0183 (Recurso Patrón)

Descripción

Este patrón permite solicitar una operación a un objeto sin conocer realmente el contenido de esta operación, ni el receptor real de la misma. Para ello se encapsula la petición como un objeto, con lo que además se facilita la parametrización de los métodos.

Nombre

Este patrón también es conocido como Acción o Transacción

Patrones Relacionados

  • Factoría: Ofrece una forma alternativa de llamar a los comandos además del uso del command manager.
  • Intérprete: Se puede implementar un pequeño Intérprete mediante clases Comando.
  • Plantilla: Puede servir para implementar la lógica de Deshacer de forma un tanto automática o a alto nivel.
  • Composite: Permite realizar agrupaciones de comandos de forma similar a una macro.
  • Prototipo: Hay quien lo utiliza para implementar la copia del comando al histórico de comandos.

Clasificación

Patrón de comportamiento

Motivación

El concepto de comando es muy ambiguo y complejo pero esta muy extendido. Podemos mencionar como ejemplos:

  • Interpretes de comandos del sistema operativo
  • Lenguajes de macros
  • Gestores de bases de datos
  • Protocoles de servidores de internet.

Es necesario encontrar un patrón que permita parametrizar a los clientes con distintas peticiones, hacer colas de peticiones, llevar un registro de las peticiones realizadas y que pueda deshacer el estado y el efecto de las mismas. El patrón Comando nos permite realizar todo esto.

Aplicabilidad

  • Parametrizar objetos mediante una acción
  • Especificar, encolar y ejecutar peticiones en distintos momentos (el objeto Comando tiene un tiempo de vida distinto al de la petición)
  • Independizar el momento de petición del de ejecución.
  • Mantener operaciones que permitan deshacer la petición.
  • Acciones que permitan la recuperación del sistema.
  • Interfaz común que permita invocar las acciones de modo uniforme y extender el sistema de modo sencillo.

Estructura

La representación gráfica del patrón es la siguiente:

Participantes

  • Comando: Clase que ofrece un interfaz para la ejecución de órdenes. Define los métodos do y undo que se implementarán en cada clase concreta.
  • ComandoConcreto: Clase que implementa una orden concreta y sus métodos do y undo. Su constructor debe inicializar los parámetros de la orden.
  • Cliente: crea un comando concreto e indica a quién va dirigido
  • Invocador: contiene el comando asociado a la petición
  • Receptor: Sabe realizar las operaciones asociadas a una peticion. Cualquier clase puede actuar como receptor.

Colaboraciones

  • Cliente crea un objeto ComandoConcreto y asocia un receptor.
  • Invocador almacena el objeto ComandoConcreto.
  • Invocador lanza la petición llamando al metodo do de Comando. Si es un Comando con operaciones de vuelta atras, ComandoConcreto almacena el estado previo a la modificación.
  • El objeto ComandoConcreto invoca a operaciones en el receptor.

Consecuencias

  • Desacopla el objeto que invoca a la operación del que sabe como llevarla a cabo.
  • Los comandos son entidades de "primer orden", se pueden manipular y extender como cualquier otro objeto.
  • Se pueden crear macro-comandos mediante el uso del patrón Compositor.
  • Es facil añadir nuevos comandos ya que no es necesario modificar las clases existentes.

Implementación

A la hora de hacer recomendaciones sobre la implementación de este patrón es necesario tener claro los dos conceptos siguientes:

  • ¿Cómo de inteligente debe ser un Comando? Un Comando puede implementarse con dos habilidades consideradas extremas. La primera de estas habilidades  es invocar una acción en el receptor. La segunda de estas habilidades consideradas extremas es implementar el comportamiento sin delegar (muy útil para comandos independientes del receptor o cuando este está implícito)
  • ¿Cómo implementar las operaciones de vuelta atras y rehacer (operaciones undo y redo)? Hay que tener en cuenta que deben de ser operaciones adicionales al patrón. Es necesario almacenar el estado previo a la ejecución del Comando: objeto receptor, argumentos de la operación, valores del receptor que puedan ser modificados. Si se crea una tabla de estados anteriores se permitirá volver hacia atrás todos los estados.

Código de ejemplo

A continuación mostramos un ejemplo de la implementación del patrón.

public interface Comando {
  public void execute();
  }

public class ComandoGenerarNominas implements Comando {
  private Universidad anduniversidad;
  public ComandoGenerarNominas (Universidad universidad) {
    anduniversidad = universidad;
  }
  public void ejecuta() {
    anduniversidad.generarNominas();
  }
}

public class MenuUniversidad {
  public boolean menuPrincipal {
  ...
  case 3: // generar nóminas
          // anduniversidad.generarNominas();
    Comando comando = new ComandoGenerarNominas(anduniversidad);
    comando.ejecuta();
    break;
  }
}

Usos conocidos

Las clases Button y MenuItem de Java facilitan la utilización de este patrón, declarando los métodos getActionCommand y setActionCommand para dar nombres a las acciones realizadas por los objetos, facilitándose una correspondencia entre ambos.

Contenidos relacionados

Recursos
Área: Desarrollo » Patrones de Diseño
Código Título Tipo Carácter
RECU-0013 Patrones de diseño Ficha Recomendado
RECU-0190 Factoría Patrón Recomendado
RECU-0192 Intérprete Patrón Recomendado
RECU-0198 Plantilla Patrón Recomendado
RECU-0184 Composite Patrón Recomendado
RECU-0199 Prototipo Patrón Recomendado