Volver a la página principal
domingo 7 julio 2024
36

Implementación del Patrón de Diseño Memento en Java

¿Qué es el Patrón de Diseño Memento?

El patrón Memento se encarga de capturar y externalizar el estado interno de un objeto para que este pueda ser restaurado más adelante sin exponer los detalles internos del objeto. Es especialmente útil en situaciones donde es necesario realizar un seguimiento del estado de un objeto en diferentes momentos del tiempo.

Beneficios del Patrón de Diseño Memento

1. Encapsulación de Estados: Permite guardar el estado de un objeto sin violar su encapsulación.

2. Deshacer y Rehacer: Facilita la implementación de funcionalidades de deshacer y rehacer en aplicaciones.

3. Simplicidad en el Manejo de Estados: Simplifica la gestión de estados complejos en objetos.

Componentes del Patrón Memento

El patrón Memento se compone de tres elementos clave:

1. Originador: El objeto que tiene un estado interno y puede crear un Memento de su estado actual y restaurarlo a partir del mismo.

2. Memento: El objeto que almacena el estado interno del Originador.

3. Cuidador (Caretaker): El encargado de almacenar y restaurar los Mementos sin modificar su contenido.

Originador

El Originador es la clase cuyos estados queremos salvar y restaurar. Esta clase contiene una función para crear un Memento y otra para restaurar su estado desde un Memento.

public class Originador {
    private String estado;

    public void setEstado(String estado) {
        this.estado = estado;
    }

    public String getEstado() {
        return estado;
    }

    public Memento guardarEstadoEnMemento() {
        return new Memento(estado);
    }

    public void obtenerEstadoDeMemento(Memento memento) {
        estado = memento.getEstado();
    }

    public static class Memento {
        private final String estado;

        public Memento(String estado) {
            this.estado = estado;
        }

        private String getEstado() {
            return estado;
        }
    }
}

Memento

El Memento es una clase anidada estática dentro del Originador que almacena el estado. Esta clase es privada para proteger el estado del Originador.

Cuidador (Caretaker)

El Cuidador es responsable de guardar los Mementos. Esta clase no modifica ni examina el contenido de los Mementos.

import java.util.ArrayList;
import java.util.List;

public class Cuidador {
    private List<Originador.Memento> mementoList = new ArrayList<>();

    public void addMemento(Originador.Memento memento) {
        mementoList.add(memento);
    }

    public Originador.Memento getMemento(int index) {
        return mementoList.get(index);
    }
}

Implementación del Patrón Memento en Java

Vamos a implementar el patrón Memento paso a paso para entender mejor cómo funcionan los componentes juntos.

Paso 1: Definición de la Clase Originador

El Originador es la clase que queremos proteger y gestionar su estado.

public class Originador {
    private String estado;

    public void setEstado(String estado) {
        this.estado = estado;
    }

    public String getEstado() {
        return estado;
    }

    public Memento guardarEstadoEnMemento() {
        return new Memento(estado);
    }

    public void obtenerEstadoDeMemento(Memento memento) {
        estado = memento.getEstado();
    }

    public static class Memento {
        private final String estado;

        public Memento(String estado) {
            this.estado = estado;
        }

        private String getEstado() {
            return estado;
        }
    }
}

Paso 2: Creación de la Clase Memento

La clase Memento es anidada dentro del Originador y no expone su estado directamente.

Paso 3: Implementación del Cuidador

El Cuidador almacena los Mementos sin conocer su contenido.

import java.util.ArrayList;
import java.util.List;

public class Cuidador {
    private List<Originador.Memento> mementoList = new ArrayList<>();

    public void addMemento(Originador.Memento memento) {
        mementoList.add(memento);
    }

    public Originador.Memento getMemento(int index) {
        return mementoList.get(index);
    }
}

Paso 4: Integración de las Clases

Finalmente, integramos estas clases para ver cómo funcionan juntas.

public class MementoPatternDemo {
    public static void main(String[] args) {
        Originador originador = new Originador();
        Cuidador cuidador = new Cuidador();

        originador.setEstado("Estado #1");
        originador.setEstado("Estado #2");
        cuidador.addMemento(originador.guardarEstadoEnMemento());

        originador.setEstado("Estado #3");
        cuidador.addMemento(originador.guardarEstadoEnMemento());

        originador.setEstado("Estado #4");
        System.out.println("Estado actual: " + originador.getEstado());

        originador.obtenerEstadoDeMemento(cuidador.getMemento(0));
        System.out.println("Primer estado guardado: " + originador.getEstado());
        originador.obtenerEstadoDeMemento(cuidador.getMemento(1));
        System.out.println("Segundo estado guardado: " + originador.getEstado());
    }
}

Casos de Uso del Patrón Memento

El patrón Memento es ideal en situaciones donde es necesario mantener un historial de estados. Algunos ejemplos incluyen:

Aplicaciones de Undo y Redo

Implementar funcionalidades de deshacer y rehacer

en editores de texto, aplicaciones de dibujo, y similares.

Gestión del Estado de Objetos Complejos

Manejo de estados complejos en juegos, simulaciones y aplicaciones financieras.

Mejores Prácticas y Consideraciones

  • Encapsulamiento: Mantener el estado del Memento privado para proteger el encapsulamiento del Originador.
  • Gestión de Memoria: Considerar el impacto en la memoria al almacenar múltiples estados.
  • Uso Adecuado: Utilizar el patrón Memento solo cuando sea necesario para evitar complicaciones innecesarias.

FAQs sobre el Patrón de Diseño Memento en Java

¿Cuándo debo usar el patrón Memento?

El patrón Memento es ideal para implementar funcionalidades de deshacer y rehacer, y para manejar estados de objetos complejos.

¿Cuáles son las limitaciones del patrón Memento?

El principal inconveniente es el uso de memoria adicional para almacenar múltiples estados.

¿Cómo afecta el rendimiento el uso del patrón Memento?

El impacto en el rendimiento depende de la frecuencia y el tamaño de los estados almacenados.

¿Se puede utilizar el patrón Memento con otros patrones de diseño?

Sí, el patrón Memento se puede combinar con otros patrones de diseño como el Comando y el Estado para crear soluciones más robustas.

Conclusión

El patrón de diseño Memento es una herramienta poderosa para gestionar estados de objetos en Java, ofreciendo una solución elegante para implementar funcionalidades de deshacer y rehacer. Su correcta implementación puede mejorar significativamente la robustez y la mantenibilidad del código.

Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer