Esta página ou seção foi marcada para revisão devido a incoerências ou dados de confiabilidade duvidosa.Dezembro de 2008) ( |
Predefinição:Manutenção/Categorizando por assunto
Memento é um padrão de projeto de software documentado no Catálogo Gang of Four, sendo considerado como um padrão comportamental. Ele permite armazenar o estado interno de um objeto em um determinando momento, para que seja possível retorná-lo a este estado, sem que isso cause problemas com o encapsulamento.[1]
Ele funciona de maneira que uma classe é responsável por salvar o estado do objeto desejado enquanto que uma outra classe fica responsável por armazenar todas essas copias (mementos).
O padrão Memento é implementado se utilizando de três elementos: Originador, Armazenador e o Memento.
Motivação
O Padrão Comportamental Memento possui uma grande gama de aplicações onde é necessário a recuperação de um estado anterior de um objeto como um todo, qualquer tipo de editor precisa oferecer uma maneira de desfazer ações como restaurar imagens, textos etc. Para isso, o padrão Memento procura recuperar o estado anterior dessas ações e copiar os mesmos para um objeto a ser restaurado.
Participantes
Três objetos estão envolvidos na implementação do padrão Memento.
- Originador
- é o objeto cujo estado se deseja capturar.
- Memento
- responsável por armazenar o estado interno do objeto Originador.
- Armazenador
- é o objeto que acessará o originador, e deseja desfazer qualquer mudança efetuada, caso necessário.
- ele é responsável por armazenar todos os Mementos.
- os Mementos devem ser recuperados de maneira LIFO (Last In First Out) onde o ultimo adicionado será o primeiro a ser recuperado.
O Armazenador 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.
Funcionamento
O objeto representado na classe Originador cria um novo memento a partir de si próprio, é ele que vai controlar toda a execução do Padrão Memento, criando uma nova instância da classe Armazenador, sempre que haja alguma modificação derivada de ações do sistema e de seu funcionamento padrão, o Originador irá criar um novo Memento, externalizando seu estado interno para um novo objeto que se tornará o Memento que será armazenado para posterior restauração. Além dos métodos e atributos próprios do objeto a ser restaurado, o Originador conta com um atributo que represente o estado atual do mesmo, métodos para definir e atribuir o estado, e métodos para salvar e solicitar o estado a partir do Memento.
Com o estado salvo no Objeto Memento, o Originador volta suas atenções para o Armazenador, quando o método que aciona a ação de modificação é invocado, o Memento é criado e adicionado no Armazenador, que, a partir de agora guardará os Mementos em uma pilha, usando o LIFO, para tanto, o Armazenador possui uma lista do tipo do Memento, possui métodos para adicionar um novo Memento e para acessar o ultimo adicionado na pilha do Armazenador, quando o ultimo for retirado, o topo da lista será o Memento com o estado anterior ao que foi solicitado, e assim por diante, até que não haja mais Mementos para serem acessados, nesse momento deve ser lançada uma exceção.
Contras
O problema do Memento é que por ele sempre estar guardando o estado do objeto, ele pode guardar objetos demais e de maneira desnecessária e assim utilizando muito da memória da máquina.
Implementação
O código em java a seguir ilustra a utilização do memento para desfazer ações de mudança de estado.
import java.util.List; import java.util.ArrayList; class Originator { private String state;
public void setState(String state) { System.out.println("Originator: Mudando estado para " + state); this.state = state; }
public Memento saveState() { System.out.println("Originator: Salvando o Memento."); return new Memento(this.state); }
public void restoreState(Memento memento) { this.state = memento.getSavedState(); System.out.println("Originator: Estado após restaurar o Memento: " + state); }
public static class Memento { private final String state;
public Memento(String stateToSave) { this.state = stateToSave; }
private String getSavedState() { return this.state; } } }
class Armazenador { public static void main(String[] args) { List<Originator.Memento> savedStates = new ArrayList<>();
Originator originator = new Originator(); originator.setState("Estado1"); originator.setState("Estado2");
savedStates.add(originador.saveState()); originator.setState("Estado3");
// Podemos ter múltiplos mementos e escolher qual queremos restaurar. savedStates.add(originator.saveState()); originator.set("Estado4");
originador.restoreState(savedStates.get(1)); } }
A saída deste código é:
Originador: Mudando estado para Estado1 Originador: Mudando estado para Estado2 Originador: Salvando o Memento. Originador: Mudando estado para Estado3 Originador: Salvando o Memento. Originador: Mudando estado para Estado4 Originador: Estado apos restaurar o Memento: Estado3
Este exemplo utiliza uma String como o estado, o que é um objeto imutável em Java. Em cenários da vida real, o estado na maioria das vezes é um objeto, neste caso uma copia do objeto deve ser feita.
Predefinição:Padrões de projeto
- ↑ Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (1994). Design Patterns: Elements of Reusable Object-Oriented Software. [S.l.]: Addison Wesley. pp. 283ff. ISBN 0-201-63361-2