Command – Patrones de Diseño
Antonio Leiva

El patrón de diseño Command es un patrón de diseño de software que se utiliza para encapsular una solicitud como un objeto, de modo que se pueda parametrizar con diferentes solicitudes, enviar solicitudes por separado a colas o registrar y reproducir operaciones.

Este patrón se basa en la idea de tratar las operaciones de la misma manera que los datos, lo que permite tratar a las operaciones de forma genérica y separar la ejecución de una operación de su implementación.

Ejemplo 1: Sistema de luces inteligentes

Un ejemplo común de la utilización del patrón Command es en la implementación de un sistema de control de luces en una casa inteligente.

En este caso, cada luz podría ser representada por un objeto que puede ejecutar objetos de tipo Command, y cada acción que se pueda realizar sobre una luz (encender, apagar, cambiar de color, etc.) se implementaría como una clase concreta que implemente la interfaz Command.

De esta forma, se pueden crear diferentes objetos Command que representen diferentes acciones sobre una luz, y enviarlos al objeto Luz para que se ejecuten.

En Kotlin, podemos implementar el patrón Command de la siguiente manera:

interface Command {
  fun execute()
}

class TurnOnLight: Command {
  override fun execute() {
    // Code to turn on a light
  }
}

class TurnOffLight: Command {
  override fun execute() {
    // Code to turn off a light
  }
}

class Light {
  private val commands = mutableListOf<Command>()

  fun addCommand(command: Command) {
    commands.add(command)
  }

  fun executeCommands() {
    commands.forEach { it.execute() }
  }
}

fun main() {
  val light = Light()
  light.addCommand(TurnOnLight())
  light.addCommand(TurnOffLight())
  light.executeCommands()
}

En este ejemplo, hemos creado una interfaz Command que define el método execute(), que será implementado por las clases concretas que representen diferentes acciones sobre una luz. Luego, hemos creado dos clases concretas que implementan la interfaz Command: TurnOnLight y TurnOffLight. Estas clases contienen la lógica para encender y apagar una luz, respectivamente.

Finalmente, hemos creado una clase Light que tiene una lista de objetos Command y un método que permite añadir nuevos objetos Command a esta lista.

La clase Light también tiene un método executeCommands() que itera sobre la lista de objetos Command y ejecuta el método execute() de cada uno de ellos. De esta forma, se pueden enviar diferentes acciones a una luz y ejecutarlas en el orden en que se han agregado a la lista de commands.

Por ejemplo, en el código anterior podríamos crear una clase ChangeLightColor que implemente la interfaz Command y agregarla a la lista de commands en la luz. Cuando se llame al método executeCommands(), se ejecutarán en orden las acciones de encender la luz, cambiarle el color y apagarla.

De esta forma, el patrón Command nos permite tratar a las operaciones de un sistema de forma genérica y separar su ejecución de su implementación, lo que nos permite crear sistemas flexibles y modulares.

Ejemplo 2: Sistema de ventanas de escritorio

En este ejemplo, hemos creado una interfaz Command que define el método execute(), que será implementado por las clases concretas que representen diferentes acciones sobre una ventana emergente.

Luego, hemos creado tres clases concretas que implementan la interfaz Command: OpenWindow, CloseWindow y ResizeWindow.

Estas clases contienen la lógica para abrir, cerrar y cambiar el tamaño de una ventana emergente, respectivamente.

Finalmente, hemos creado una clase PopUpWindow que tiene una lista de objetos Command y un método que permite añadir nuevos objetos Command a esta lista. La clase PopUpWindow también tiene un método executeCommands() que itera sobre la lista de objetos Command y ejecuta el método execute() de cada uno de ellos. De esta forma, se pueden enviar diferentes acciones a una ventana emergente y ejecutarlas en el orden en que se han agregado a la lista de commands.

Aquí puedes ver un ejemplo en Kotlin de cómo se podría implementar el patrón Command en este caso:

interface Command {
  fun execute()
}

class OpenWindow: Command {
  override fun execute() {
    // Código para abrir una ventana emergente
  }
}

class CloseWindow: Command {
  override fun execute() {
    // Código para cerrar una ventana emergente
  }
}

class ResizeWindow: Command {
  override fun execute() {
    // Código para cambiar de tamaño una ventana emergente
  }
}

class PopUpWindow {
  private val commands = mutableListOf<Command>()

  fun addCommand(command: Command) {
    commands.add(command)
  }

  fun executeCommands() {
    commands.forEach { it.execute() }
  }
}

fun main() {
  val window = PopUpWindow()
  window.addCommand(OpenWindow())
  window.addCommand(ResizeWindow())
  window.addCommand(CloseWindow())
  window.executeCommands()
}

Conclusión

En conclusión, el patrón de diseño Command es un patrón de diseño de software que nos permite encapsular una solicitud como un objeto y tratar a las operaciones de forma genérica y separada de su implementación.

Esto nos permite crear sistemas flexibles y modulares que permiten parametrizar diferentes solicitudes, enviar solicitudes por separado a colas o registrar y reproducir operaciones.

El patrón Command es ampliamente utilizado en diferentes contextos y puede ser implementado en cualquier lenguaje de programación, como lo hemos visto en nuestro ejemplo en Kotlin.

Quizá también te interese…

Las reglas FIRST de los tests

Las reglas FIRST de los tests

Las reglas FIRST son un conjunto de principios que se utilizan para diseñar y escribir tests de software de manera efectiva. Las siglas FIRST significan: F - Fast: Un test debe ser rápido de ejecutar. I - Independent: Un test debe ser independiente de otros tests y...

¿Qué son los dobles de test?

¿Qué son los dobles de test?

Los dobles de prueba (también conocidos como "doubles" o "fakes") son herramientas comunes en la programación y en particular en el testing de software. Se utilizan para simular el comportamiento de una dependencia de una aplicación en un entorno de pruebas, sin tener...

Kata del TicTacToe en Kotlin

Kata del TicTacToe en Kotlin

Escribe el código para representar una entidad que almacene el tablero de juego del 3 en raya, y que además tenga: Un método move() con 2 parámetros, fila y columna, que permita añadir un movimiento al tablero Un método findWinner(), que devuelva el ganador (X, Y o...

0 comentarios

Enviar un comentario

Los datos personales que proporciones a través de este formulario quedarán registrados en un fichero de DevExpert, S.L.U., con el fin de gestionar los comentarios que realizas en este blog. La legitimación se realiza a través del consentimiento de la parte interesada. Si no se acepta, no podrás comentar en este blog. Los datos que proporciona solo se utilizan para evitar el correo no deseado y no se usarán para nada más. Puede ejercer los derechos de acceso, rectificación, cancelación y oposición en contacto@devexperto.com.

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Acepto la política de privacidad *