Article image
Giovanni Rozza
Giovanni Rozza04/05/2023 21:53
Compartilhe

[sw design pattern] Memento (Lembrança)

    Os padrões de design GoF são classificados em três categorias: Criacionais, Comportamentais e Estruturais. Os padrões criacionais tratam da criação de objetos, enquanto os padrões estruturais lidam com a estrutura das classes, como herança e composição. Por fim, os padrões comportamentais lidam com a comunicação entre objetos e suas interações. Estes padrões de projeto se encontram no livro “Padrões de Projetos: Soluções Reutilizáveis de Software Orientado a Objetos” escrito por 4 autores denominados GoF (Gang of Four).

    O padrão Memento é um padrão de design comportamental que permite capturar e armazenar o estado interno de um objeto sem violar o encapsulamento. Isso permite que o objeto seja restaurado para um estado anterior, se necessário. O padrão é composto por três partes principais: o Originador, o Memento e o Zelador.

    O Originador é o objeto que possui o estado interno que precisa ser salvo. Ele cria um Memento que contém uma cópia do estado interno atual e o passa para o Zelador para armazenamento.

    O Memento é uma classe que contém uma cópia do estado interno do Originador. O Zelador é responsável por armazenar e gerenciar os Mementos. Aqui está um exemplo em Java que demonstra o padrão Memento:

    public class Originador {
      private String estado;
    
    
      public void setEstado(String estado) {
          this.estado = estado;
      }
    
    
      public Memento salvarEstado() {
          return new Memento(estado);
      }
    
    
      public void restaurarEstado(Memento memento) {
          estado = memento.getEstadoSalvo();
      }
    }
    
    
    public class Memento {
      private String estadoSalvo;
    
    
      public Memento(String estado) {
          estadoSalvo = estado;
      }
    
    
      public String getEstadoSalvo() {
          return estadoSalvo;
      }
    }
    
    
    public class Zelador {
      private Memento memento;
    
    
      public void setMemento(Memento memento) {
          this.memento = memento;
      }
    
    
      public Memento getMemento() {
          return memento;
      }
    }
    
    
    public class Exemplo {
      public static void main(String[] args) {
          Originador originador = new Originador();
          Zelador zelador = new Zelador();
    
    
          originador.setEstado("Estado 1");
          originador.setEstado("Estado 2");
          zelador.setMemento(originador.salvarEstado());
    
    
          originador.setEstado("Estado 3");
          zelador.setMemento(originador.salvarEstado());
    
    
          originador.setEstado("Estado 4");
    
    
          System.out.println("Estado atual: " + originador.getEstado());
    
    
          originador.restaurarEstado(zelador.getMemento());
    
    
          System.out.println("Estado restaurado: " + originador.getEstado());
      }
    }
    

    Neste exemplo, o Originador é representado pela classe Originador, que possui um estado interno representado pela variável estado. O método setEstado é usado para atualizar o estado interno do objeto. O método salvarEstado cria um novo objeto Memento que contém uma cópia do estado interno atual do Originador.

    A classe Memento representa o objeto Memento, que contém uma cópia do estado interno do Originador. O método getEstadoSalvo é usado para obter o estado interno salvo.

    A classe Zelador é responsável por armazenar e gerenciar os objetos Memento. O método setMemento é usado para armazenar um novo objeto Memento e o método getMemento é usado para obter o objeto Memento mais recente.

    No método main, um novo objeto Originador e Zelador são criados. O estado interno do Originador é atualizado várias vezes e um novo objeto Memento é criado e armazenado no Zelador após cada atualização. O estado interno do Originador é então restaurado para um estado anterior usando o objeto Memento mais recente armazenado no Zelador.

    Em resumo, o padrão Memento permite que o estado interno de um objeto seja salvo e restaurado sem violar o encapsulamento. Isso é útil em situações em que é necessário desfazer uma série de alterações em um objeto. O resultado do código de exemplo será:

    Estado atual: Estado 4
    Estado restaurado: Estado 3
    

    Isso ocorre porque o estado do objeto Originador é atualizado várias vezes e um novo objeto Memento é criado e armazenado no objeto Zelador após cada atualização. O estado do objeto Originador é então restaurado para um estado anterior usando o objeto Memento mais recente armazenado no objeto Zelador.

    Neste caso, o estado do objeto Originador é atualizado para "Estado 1", depois para "Estado 2", em seguida, um objeto Memento é criado e armazenado no objeto Zelador. O estado do objeto Originador é então atualizado para "Estado 3", outro objeto Memento é criado e armazenado no objeto Zelador, e finalmente o estado do objeto Originador é atualizado para "Estado 4".

    Quando o estado do objeto Originador é restaurado para um estado anterior usando o objeto Memento mais recente armazenado no objeto Zelador, o estado do objeto Originador é restaurado para "Estado 3". Isso ocorre porque o objeto Memento mais recente armazenado no objeto Zelador foi criado quando o estado do objeto Originador era "Estado 3".

    Algumas possíveis relações do padrão Memento com outros padrões de projeto são:

    1. Padrão Command: O padrão Command pode ser usado em conjunto com o padrão Memento para implementar desfazer/ refazer. O objeto Command pode armazenar um objeto Memento que representa o estado anterior do objeto receptor antes de executar uma operação. Se a operação precisar ser desfeita, o objeto Command pode restaurar o estado anterior do objeto receptor a partir do objeto Memento.
    2. Padrão State: O padrão State pode ser usado em conjunto com o padrão Memento para implementar transições de estado. O objeto Memento pode armazenar o estado anterior do objeto receptor, que pode ser restaurado se a transição de estado falhar ou precisar ser desfeita.
    3. Padrão Iterator: O padrão Iterator pode ser usado em conjunto com o padrão Memento para percorrer uma lista de objetos Memento. Isso pode ser útil se você precisar implementar desfazer/ refazer em uma lista de objetos.
    4. Padrão Composite: O padrão Composite pode ser usado em conjunto com o padrão Memento para capturar e restaurar o estado de um objeto composto. O objeto Memento pode armazenar o estado de todos os objetos filhos do objeto composto, permitindo que você restaure o estado completo do objeto composto.

    Aqui está um exemplo de código em Java que demonstra o padrão Memento em conjunto com o padrão Command:

    javaCopy// Classe Memento
    public class EditorMemento {
      private final String conteudo;
    
    
      public EditorMemento(String conteudo) {
          this.conteudo = conteudo;
      }
    
    
      public String getConteudo() {
          return conteudo;
      }
    }
    
    
    // Classe Editor
    public class Editor {
      private String conteudo;
    
    
      public void escrever(String conteudo) {
          this.conteudo = conteudo;
      }
    
    
      public EditorMemento salvar() {
          return new EditorMemento(conteudo);
      }
    
    
      public void restaurar(EditorMemento memento) {
          conteudo = memento.getConteudo();
      }
    }
    
    
    // Classe Command
    public interface Comando {
      void executar();
      void desfazer();
    }
    
    
    // Classe ComandoEscrever
    public class ComandoEscrever implements Comando {
      private final Editor editor;
      private final String conteudoAnterior;
    
    
      public ComandoEscrever(Editor editor) {
          this.editor = editor;
          this.conteudoAnterior = editor.getConteudo();
      }
    
    
      @Override
      public void executar() {
          editor.escrever("Novo conteúdo");
      }
    
    
      @Override
      public void desfazer() {
          editor.restaurar(new EditorMemento(conteudoAnterior));
      }
    }
    
    
    // Classe Cliente
    public class Cliente {
      public static void main(String[] args) {
          Editor editor = new Editor();
          Comando comando = new ComandoEscrever(editor);
    
    
          // Escreve novo conteúdo
          comando.executar();
    
    
          // Salva o estado atual do editor
          EditorMemento memento = editor.salvar();
    
    
          // Escreve outro conteúdo
          comando.executar();
    
    
          // Desfaz a última operação
          comando.desfazer();
    
    
          // Restaura o estado anterior do editor
          editor.restaurar(memento);
      }
    }
    
    

    Aqui está uma explicação do código acima:

    • Classe Memento: A classe EditorMemento é uma classe que representa um objeto Memento. Ela tem um atributo conteudo que armazena o estado interno do objeto Editor em um determinado momento no tempo. A classe tem um construtor que recebe o conteúdo do editor e um método getConteudo() que retorna o conteúdo armazenado.
    • Classe Editor: A classe Editor é uma classe que representa o objeto que deseja salvar e restaurar seu estado interno. Ela tem um método escrever() que permite que você escreva um novo conteúdo no editor, um método salvar() que cria um objeto Memento contendo o estado atual do editor e um método restaurar() que restaura o estado do editor a partir de um objeto Memento.
    • Classe Command: A interface Comando é uma interface que define a interface para um objeto Command. Ela tem dois métodos: executar() e desfazer(). O método executar() é usado para executar a solicitação encapsulada pelo objeto Command, e o método desfazer() é usado para desfazer a solicitação.
    • Classe ComandoEscrever: A classe ComandoEscrever é uma classe que implementa a interface Comando. Ela encapsula a solicitação de escrever um novo conteúdo no editor. Ela tem um construtor que recebe um objeto Editor e armazena o conteúdo anterior do editor em uma variável. O método executar() escreve um novo conteúdo no editor, e o método desfazer() restaura o conteúdo anterior do editor a partir do objeto Memento.
    • Classe Cliente: A classe Cliente é uma classe que contém o método main(). Ela cria um objeto Editor e um objeto ComandoEscrever. Ela executa o método executar() do objeto ComandoEscrever para escrever um novo conteúdo no editor e, em seguida, salva o estado atual do editor em um objeto Memento. Em seguida, ela executa o método executar() novamente para escrever outro conteúdo no editor. Em seguida, ela executa o método desfazer() do objeto ComandoEscrever para desfazer a última operação e, finalmente, restaura o estado anterior do editor a partir do objeto Memento.

    links externos com mais exemplos do padrão Memento:

    —> O código do link abaixo é um exemplo de implementação do padrão de projeto Memento em Java. Ele consiste em três classes principais: TextEditor, TextWindow e TextWindowState.

    • Classe TextEditor: A classe TextEditor é uma classe que representa o objeto que deseja salvar e restaurar seu estado interno. Ela tem um atributo textWindow que é uma instância da classe TextWindow.
    • Classe TextWindow: A classe TextWindow é uma classe que representa o estado interno do objeto TextEditor. Ela tem um atributo currentText que é um objeto StringBuilder que armazena o texto atual.
    • Classe TextWindowState: A classe TextWindowState é uma classe que representa um objeto Memento. Ela tem um atributo text que armazena o estado interno do objeto TextWindow em um determinado momento no tempo. A classe tem um construtor que recebe o texto atual do TextWindow e um método getText() que retorna o texto armazenado.
    • Métodos save() e restore(): A classe TextWindow tem dois métodos: save() e restore(). O método save() cria um objeto TextWindowState contendo o estado atual do TextWindow. O método restore() restaura o estado do TextWindow a partir de um objeto TextWindowState.
    • Métodos hitSave() e hitUndo(): A classe TextEditor tem dois métodos: hitSave() e hitUndo(). O método hitSave() chama o método save() do objeto TextWindow para salvar o estado atual em um objeto TextWindowState. O método hitUndo() chama o método restore() do objeto TextWindow para restaurar o estado anterior a partir do objeto TextWindowState salvo.
    • Método write(): A classe TextEditor tem um método write() que permite escrever um novo texto no TextWindow.
    • Método print(): A classe TextEditor tem um método print() que retorna o texto atual do TextWindow.

    O exemplo cria um objeto TextEditor e escreve duas linhas de texto no TextWindow. Em seguida, ele chama o método hitSave() para salvar o estado atual do TextWindow. Em seguida, ele escreve outra linha de texto no TextWindow. Em seguida, ele chama o método hitUndo() para desfazer a última operação e restaurar o estado anterior do TextWindow. Finalmente, ele verifica se o texto atual do TextWindow é igual ao texto original.

    https://www.baeldung.com/java-memento-design-pattern

    O código do blog abaixo é um exemplo do padrão de design Memento em Java. Ele consiste em quatro classes: Employee, EmployeeMemento, EmployeeCaretaker e Main.

    • Classe Employee: A classe Employee representa um objeto de funcionário com atributos como empId, name, designation, salary, department e project. Ela tem métodos para obter e definir esses atributos, bem como métodos para criar e restaurar mementos.
    • Classe EmployeeMemento: A classe EmployeeMemento representa um objeto de memento que armazena o estado de um objeto Employee. Ela tem atributos para cada um dos atributos de Employee e um construtor para criar um novo memento.
    • Classe EmployeeCaretaker: A classe EmployeeCaretaker é responsável por armazenar e recuperar mementos para objetos Employee. Ela usa um mapa para armazenar mementos para cada funcionário e fornece métodos para adicionar e recuperar mementos.
    • Classe Main: A classe Main é o ponto de entrada do programa. Ela cria dois objetos Employee, define seus atributos, cria mementos e os adiciona ao EmployeeCaretaker. Em seguida, modifica os objetos Employee, cria novos mementos e os adiciona ao EmployeeCaretaker. Finalmente, recupera mementos do EmployeeCaretaker e restaura os objetos Employee para seus estados anteriores.

    O exemplo demonstra como usar o padrão de design Memento para salvar e restaurar o estado de um objeto. Ele usa a classe Employee para representar um objeto com estado, a classe EmployeeMemento para armazenar o estado e a classe EmployeeCaretaker para gerenciar os mementos. A classe Main mostra como criar, modificar e restaurar objetos Employee usando mementos.

    https://dzone.com/articles/memento-design-pattern-in-java

    REFERÊNCIAS:

    Compartilhe
    Comentários (2)
    michael oliveira
    michael oliveira - 05/05/2023 17:50

    parabéns giovanni rozza fico top

    SN

    Sergio Napolitano - 04/05/2023 22:17

    show!

    Muito bom!