Menu
Coddy logo textTech

Patrón Command

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 94 de 110.

El patrón Command encapsula una solicitud como un objeto, lo que permite parametrizar clientes con diferentes solicitudes, encolar operaciones o admitir la funcionalidad de deshacer. En lugar de llamar directamente a un método, envuelves la acción en un objeto de comando que puede ser almacenado, pasado o ejecutado más tarde.

El patrón involucra tres componentes clave: una interfaz Command con un método execute, Concrete Commands que implementan acciones específicas y un Receiver que realiza el trabajo real. Un Invoker opcional activa los comandos sin saber qué hacen:

abstract class Command {
  void execute();
}

class Light {
  void turnOn() => print('Light is ON');
  void turnOff() => print('Light is OFF');
}

class TurnOnCommand implements Command {
  final Light light;
  TurnOnCommand(this.light);

  @override
  void execute() => light.turnOn();
}

class TurnOffCommand implements Command {
  final Light light;
  TurnOffCommand(this.light);

  @override
  void execute() => light.turnOff();
}

class RemoteControl {
  Command? _command;

  void setCommand(Command command) {
    _command = command;
  }

  void pressButton() {
    _command?.execute();
  }
}

void main() {
  var light = Light();
  var remote = RemoteControl();

  remote.setCommand(TurnOnCommand(light));
  remote.pressButton();  // La luz está encendida

  remote.setCommand(TurnOffCommand(light));
  remote.pressButton();  // La luz está apagada
}

El RemoteControl no sabe nada sobre luces; simplemente ejecuta cualquier comando que se le asigne. Este desacoplamiento facilita la adición de nuevos comandos sin modificar el invocador. El patrón Command es ideal para implementar sistemas de deshacer/rehacer, colas de tareas o grabación de macros donde se necesita tratar las acciones como objetos de primera clase.

challenge icon

Desafío

Fácil

¡Vamos a construir un sistema de comandos para un editor de texto utilizando el patrón Command! Crearás un sistema que encapsula las operaciones de texto como objetos de comando, permitiendo que un editor ejecute diferentes acciones sin conocer los detalles de cada operación. Este es un caso de uso clásico para el patrón Command; piénsalo como un sistema de deshacer/rehacer donde cada acción se almacena como un objeto.

Organizarás tu código en dos archivos:

  • commands.dart: Crea tu sistema de comandos aquí. Comienza con una clase abstracta Command que declare un método execute(). Luego, crea una clase TextDocument (el receptor) que contenga un campo String content (inicialmente vacío) y tenga tres métodos:
    • append(String text) - añade texto al final del contenido
    • clear() - establece el contenido como una cadena vacía
    • show() - imprime Document: [content]
    Ahora implementa tres comandos concretos que trabajen con un TextDocument:
    • AppendCommand - recibe un documento y texto en su constructor, y añade el texto cuando se ejecuta
    • ClearCommand - recibe un documento en su constructor, y lo limpia cuando se ejecuta
    • ShowCommand - recibe un documento en su constructor, y muestra su contenido cuando se ejecuta
    Finalmente, crea una clase TextEditor (el invocador) que almacene una lista de comandos. Debe tener un método addCommand(Command command) para encolar comandos, y un método runAll() que ejecute todos los comandos encolados en orden.
  • main.dart: Importa tu archivo de comandos y demuestra el patrón Command. Crea un TextDocument y un TextEditor. Encola los siguientes comandos en orden: añadir Hello, añadir World, mostrar el documento, añadir !, mostrar de nuevo, limpiar el documento y mostrar una última vez. Luego, ejecuta todos los comandos encolados.

¡Observa cómo el TextEditor no sabe nada sobre añadir, limpiar o mostrar; simplemente ejecuta cualquier comando que se le asigne. ¡Este desacoplamiento es la esencia del patrón Command!

Salida esperada:

Document: Hello World
Document: Hello World!
Document: 

Pruébalo tú mismo

import 'commands.dart';

void main() {
  // TODO: Crear una instancia de TextDocument

  // TODO: Crear una instancia de TextEditor

  // TODO: Poner en cola los siguientes comandos en orden:
  // 1. Añadir "Hello"
  // 2. Añadir " World"
  // 3. Mostrar el documento
  // 4. Añadir "!"
  // 5. Mostrar el documento de nuevo
  // 6. Limpiar el documento
  // 7. Mostrar el documento una última vez

  // TODO: Ejecutar todos los comandos en cola
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos