Table of Contents
La idea de este artículo sobre cómo construir un DSL es jugar y experimentar con algunos patrones de diseño sin profundizar demasiado en ninguno de ellos.
Tendremos un personaje con una posición y mediante comandos agrupados en un DSL, podremos moverlo en 4 direcciones. Los comandos podrán deshacerse y mover al personaje a posiciones anteriores.
Character
Lo primero que vamos a crear es nuestra clase de dominio Character, donde pondremos toda la lógica referente al movimiento del personaje. Podrá moverse hacia arriba, abajo y a ambos lados.
Memento
Memento, es un patrón de diseño cuya finalidad es almacenar el estado de un objeto en un momento dado.
Crearemos nuestra clase Memento para almacenar cada uno de los estados anteriores de nuestro Character.
Originator
Originator, crea un objeto Memento conteniendo una fotografía de su estado interno.
Crearemos una interface originator y la implementaremos en nuestra clase Character para que sepa crear recuerdos y restaurarse a partir de uno de ellos.
En este punto, me he dado cuenta de que Memento no parece estar pensado para código inmutable. Lo normal sería igualar los valores de la instancia actual con los del Memento.
Command
Command, es la clase base de todos los comandos. Cada comando deberá implementar dicha interfaz y su método do, que mediante polimorfismo ejecutará acciones diferentes.
- Guardamos un recuerdo del objeto que vamos a modificar.
- El método ‘do’ será abstracto y mediante polimorfismo cada comando tendrá una implementación distinta.
- El método undo se encargará de deshacer la acción que ha realizado el comando a través del memento. La implementaremos una única vez en la clase base.
Concrete Command
Concrete Command, es cada una de los comandos que tiene nuestro sistema. Deben heredar de la clase base Command. Cada uno tendrá su propia implementación.
Es importante que los comandos no contengan lógica alguna más que llamar al método de la clase que contiene toda la lógica. Para nuestro ejemplo vamos a crear un comando para mover Character en cada dirección.
CommandManager
CommandManager, será el componente encargado de ejecutar los comandos y almacenar el histórico de estos, con la finalidad de poder deshacer y rehacer los comandos.
Cada uno de los métodos de esta clase retorna una Tupla con:
- Una nueva instancia de CommandManager con el histórico de comandos actualizado.
- Una nueva instancia del Character actualizado.
Creando el DSL
Extension methods, es un patrón que tiene la capacidad de agregar comportamiento a clases ya existentes sin necesidad de modificar las clases originales.
Haciendo uso extension methods, vamos a añadir métodos a la Tupla, para agrupar todas los comandos y construir nuestro DSL.
Usando el DSL
La salida por consola será:
Character(x=-1, y=-1)
Ahora solo nos queda añadir los comandos que creemos al DSL para extenderlo.
Author
-
Fullstack with more than 17 years of experience in different professional projects. Interested in new technologies and applying best practices for continuous improvement.
Ver todas las entradas