Back-End

25 mai, 2010

Padrão de projetos com Memento

Publicidade

Olá
pessoal, esse é o meu primeiro artigo para o iMasters e vou falar sobre um design pattern (padrão de projeto)
chamado Memento.

Você já conhece o Memento?

Segundo
o Wikipédia:

“Memento
é um padrão de projeto que permite armazenar o estado interno de um
objeto em um determinado momento, para que seja possível retorná-lo
a este estado, caso necessário.

Três objetos estão envolvidos na implementação
do padrão Memento.

  • Originador é o objeto cujo estado se deseja capturar.
  • Memento é o objeto definido dentro da classe
    Originador, com modificador de acesso privado, cujo estado do objeto
    originador será armazenado.
  • Cliente é o objeto que acessará o originador, e deseja
    desfazer qualquer mudança efetuada, caso necessário.

O cliente deve requisitar um objeto memento, antes de se valer do
originador. Após efetuar as operações desejadas no originador, o
cliente devolve a este o objeto memento, caso deseje desfazer
qualquer alteração.

O objeto memento não permite o acesso de qualquer classe além da
classe originador. Assim, tal padrão mostra-se útil por não violar
o conceito de encapsulamento.”

Para
ficar mais claro, vamos a um exemplo.

Suponhamos
que você possua um site que ofereça um serviço de customização
de carros. Onde o usuário poderá escolher a cor, jogo de rodas,
aerofólios e outros acessórios para o carro.

Imagine
ainda que cada vez que o usuário queira “salvar” determinada
configuração, você precise armazená-la para que sempre que as
alterações futuras forem desfeitas, você possa exibir o carro com
os atributos salvos anteriormente.

É
claro que existem diversas maneiras de fazer isso, mas aqui,
mostraremos como o Memento se comporta nesse tipo de situação.

Na
imagem abaixo temos um diagrama de estados que ilustra o nosso caso:

Explicando
nosso diagrama:

  • Temos
    o nosso objeto em seu estado inicial.
  • Depois
    um método inicializa o objeto com suas devidas particularidades.
  • Antes
    de realizar a customização do carro é necessário verificar se
    algum item foi escolhido.
  • Caso
    exista algum item escolhido, o objeto recebera esse item através do
    método CustomizaCarro e então teremos o nosso objeto em seu novo
    estado.
  • Caso
    não exista algum item escolhido, o objeto retorna seu estado
    normal.

Bem,
é nesse momento que o Memento vai ajudar a gente a armazenar e
recuperar o objeto em seu estado de customização a qualquer momento
no seu sistema. Onde o estado pode ser o próprio carro configurado
ou alguma característica dele.

Traduzindo
isto para a linguagem Java, teremos:

1 import java.util.List;
1 import java.util.ArrayList;
2 class Originator {
private String state;
// A classe também pode conter outros dados que não fazem parte
// do estado guardado no Memento
public void set(String state) {
System.out.println("Originator: Setando o estado para: " + state);
this.state = state;
}
public Memento saveToMemento() {
System.out.println("Originator: Salvando no Memento.");
return new Memento(state);
}
public void restoreFromMemento(Memento memento) {
state = memento.getSavedState();
System.out.println("Originator: Estado após a restauração do Memento: " + state);
}
3 public static class Memento {
private final String state;
private Memento(String stateToSave) {
state = stateToSave;
}
private String getSavedState() {
return state;
}
}
}
4 class Caretaker {
public static void main(String[] args) {
List<Originator.Memento> savedStates = new ArrayList<Originator.Memento>();
Originator originator = new Originator();
originator.set("State1");
originator.set("State2");
savedStates.add(originator.saveToMemento());
originator.set("State3");
savedStates.add(originator.saveToMemento());
originator.set("State4");
originator.restoreFromMemento(savedStates.get(1));
}
}

Explicando
o código acima, nós temos, em 1, dois
imports necessários para se trabalhar com List e ArrayList em Java.
Em 3, temos a nossa classe Memento, ela é
uma classe estática dentro do Originator que tem como função setar
ou recuperar determinado estado do objeto.

Em
2 temos o Originator, ele é o canal de
comunicação para com o Memento, é através dele que poderemos
armazenar e recuperar os estados via Memento.

Em
4 temos a classe Caretaker, note que foi
criado uma lista para salvar os estados do objeto. Depois setamos os
estados do Originator e ai chamamos os método savedStates.add
para armazenar os estados setados. Como a nossa lista é
indexada, podemos recuperar determinado estado a partir do método
originator.restoreFromMemento(savedStates.get(1)),
onde (1) é a posição do estado que se deseja recuperar.

O Memento é uma alternativa para sistemas onde os usuários fazem muitas
simulações e são necessários salvar ou desfazer essas
configurações em tempo de execução.

Mais
informações: http://sourcemaking.com/design_patterns/memento

Obrigado
a todos e até o próximo artigo.