Qué es el patron de diseño Command

Qué es el patron de diseño Command

Siguiendo nuestro curso de programación hoy veremos el patrón Command. El patrón de comportamiento Command encapsula una petición dentro de un objeto, permitiendo parametrizar a los clientes con distintas peticiones, encolarlas, guardarlas en un registro de sucesos o implementar un mecanismo de deshacer/repetir.

uml_command

Aplicaciones

Úsese el patrón Command cuando se quiera:

  • Parametrizar objetos con una determinada acción.
  • Que la acción a realizar y el objeto que lanza la petición tengan ciclos de vida distintos.
  • Permitir deshacer/repetir una acción.
  • Guardar todas las operaciones ejecutadas en un registro.
  • Usar transacciones.

Estructura

estructura_command

  • Command: Define una interfaz para ejecutar una operación
  • ConcreteCommand (PasteCommand, OpenCommand). Asocia un objeto Receiver con una acción. También implementa execute llamando a las operaciones de dicho objeto receptor.
  • Client (Application): Crea un objeto ConcreteCommand y establece su receptor.
  • Invoker (MenuItem): Ejecuta la acción.
  • Receiver (Document, ApplicaHon)

Ejemplo

Supongamos un editor de texto, una clase Document con las operaciones básicas que se hacen sobre un documento abrir, cerrar, cortar, copiar y pegar. Y otra clase Menu que tendrá unas clases que implementen esas operaciones de abrir, cerrar… pero que realmente no sabrán que acción hará.

Código

La clase aplicación que dispondrá una lista de los documentos para tratar:

public class Application {    private ArrayList<Document> documentos = new ArrayList<Document>();    private Menu m;    public void add(Document d) {        documentos.add(d);    }    public void add(Menu menu) {        m = menu;    }}

La clase Document que encapsula toda su funcionalidad:

public class Document {    public void open(){        System.out.println("Abriendo el documento");    }    public void close(){        System.out.println("Cerrando el documento");    }    public void cut(){        System.out.println("Cortando...");    }    public void copy(){        System.out.println("Copiando...");    }    public void paste(){        System.out.println("Pegando...");    }}public class Menu {    private ArrayList<MenuItem> items = new ArrayList<MenuItem>();    public void add(MenuItem m) {        items.add(m);    }}public class MenuItem {    private Command c;    private Document d;    public MenuItem(Command command, Document document) {        c = command;        d = document;    }    public void clicked() {        c.execute(d);    }}

Y la interfaz Command:

public interface Command {    public void execute(Document d);}

Implementación de pegar sería:

public class PasteCommand implements Command{    @Override    public void execute(Document d) {        d.paste();    }}

Implementación de copiar sería:

public class CopyCommand implements Command{    @Override    public void execute(Document d) {        d.copy();    }}

Y así con todas las demás operaciones que tengamos en el documento, o quequeramos que tenga.

La clave de este patrón es una interfaz Command que define una operación execute. Entonces serán estas subclases concretas de Command quienes implementan la operación y especifican el receptor de la orden.

Como siempre aquí os dejo el código utilizado.

Para ti
Queremos saber tu opinión. ¡Comenta!