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.