arquivo - Wiki LES PUC-Rio

Propaganda
Padrão de Projeto Memento
Daltro Simões Gama
11/09/2013
11/09/2013
@LES/PUC-Rio
2
Objetivo
v Considere um objeto, no qual desejamos
preservar seu estado;
v Estados do objeto em questão são
mutáveis;
v Queremos poder guardar “backups” dos
estados do objeto, para poder restaurá-lo
sob demanda.
v Padrão Memento também é conhecido
como “Token”.
11/09/2013
@LES/PUC-Rio
3
Motivação
v Podemos pensar em várias formas de se
guardar um “snapshot” de um objeto para
podermos fazer “undo” em operações
feitas sobre ele;
§  O estado de um objeto pode conter detalhes
internos do objeto, que não deveriam ser
expostos.
v O padrão Memento traz uma forma de se
implementar esta funcionalidade
preservando o princípio do
encapsulamento.
11/09/2013
@LES/PUC-Rio
4
Participantes
v Memento: O estado propriamente dito;
v Originator: O objeto que possui o
estado;
v Caretaker: Quem manipula o objeto.
v O Caretaker fará algo no Originator,
mas precisa ser capaz de desfazer as
alterações, se necessário.
11/09/2013
@LES/PUC-Rio
5
Estrutura
Memento
Caretaker
getState()
setState()
state
Originator
this.state = m.getState()
setMemento(Memento m)
createMemento()
state
return new Memento(state)
11/09/2013
@LES/PUC-Rio
6
Colaborações
umCaretaker
createMemento()
umOriginator
umMemento
new Memento
setState()
setMemento()
11/09/2013
getState()
@LES/PUC-Rio
7
Um código (JAVA) exemplo
public class Originator {
public static class Memento {
Este é um esqueleto do memento
do Originator, porém sem funcionalidade.
private Object mementoState;
Vamos inserir alguma funcionalidade nele.
private Object getState() {
return mementoState;
}
private void setState(Object argState) {
this.mementoState = argState;
}
}
private Object originatorState;
public void setMemento(Memento argMemento){
this.originatorState = argMemento.getState();
}
public Memento createMemento(){
Memento result = new Memento();
result.setState(originatorState);
return result;
}
}
11/09/2013
@LES/PUC-Rio
8
Um código (JAVA) exemplo
public class Originator {
(…)
private Object originatorState;
public void setMemento(Memento argMemento){
this.originatorState = argMemento.getState();
}
public Memento createMemento(){
Memento result = new Memento();
result.setState(originatorState);
return result;
}
Supondo que o Originator manipula o valor
public String getText(){
de um campo texto qualquer.
return originatorState.toString();
}
… ou melhor, o Originator é o próprio
campo texto.
public void setText(String newText){
originatorState = newText;
}
}
11/09/2013
@LES/PUC-Rio
9
Um código (JAVA) exemplo
public class Originator {
(…)
private String originatorState;
public void setMemento(Memento argMemento){
this.originatorState = argMemento.getState();
}
public Memento createMemento(){
Memento result = new Memento();
result.setState(originatorState); Neste caso, o estado interno é uma String.
return result;
A especialização também vale pro código
}
da classe interna Memento.
public String getText(){
return originatorState;
}
public void setText(String newText){
originatorState = newText;
}
}
11/09/2013
@LES/PUC-Rio
10
Um código (JAVA) exemplo
public class Caretaker {
private final Stack<Originator.Memento> savedStates = new Stack<Originator.Memento>();
private final Originator myOriginator;
public Caretaker(Originator myOriginator) {
this.myOriginator = myOriginator;
}
public void saveState(){
Originator.Memento theMemento = myOriginator.createMemento();
savedStates.push(theMemento);
}
public void undo(){
Originator.Memento theMemento = savedStates.pop();
myOriginator.setMemento(theMemento);
}
}
O Caretaker se encarregará de dar uma
interface de mais alto nível para o
mecanismo de undo.
11/09/2013
@LES/PUC-Rio
11
Um código (JAVA) exemplo
Agora um código que aciona tudo isso.
public static void main(String[] args) {
Originator demoOriginator = new Originator();
Caretaker demo = new Caretaker(demoOriginator);
demoOriginator.setText("Olá.");
demoOriginator.setText("Olá, sou o Memento");
demo.saveState(); // CheckPoint.
System.out.println(demoOriginator.getText());
demoOriginator.setText("Olá, sou o Memento. Vamos brincar?");
demo.saveState(); // CheckPoint.
System.out.println(demoOriginator.getText());
demoOriginator.setText("Esqueça tudo isso! Não quero mais brincar.");
demo.saveState(); // CheckPoint.
System.out.println(demoOriginator.getText());
demo.undo(); // Volta um estado.
System.out.println(demoOriginator.getText());
demo.undo(); // Volta outro estado.
System.out.println(demoOriginator.getText());
demo.undo(); // Volta mais um estado.
System.out.println(demoOriginator.getText());
}
11/09/2013
@LES/PUC-Rio
12
Um código (JAVA) exemplo
Saída do programa:
Olá, sou o Memento
Olá, sou o Memento. Vamos brincar?
Esqueça tudo isso! Não quero mais brincar.
Esqueça tudo isso! Não quero mais brincar.
Olá, sou o Memento. Vamos brincar?
Olá, sou o Memento
11/09/2013
@LES/PUC-Rio
13
Consequências
v Vantagens:
§  Preserva encapsulamento;
§  Simplifica o uso do Originator;
v Desvantagens:
§  Deve-se atentar para o uso de memória e
overhead para armazenar os estados.
11/09/2013
@LES/PUC-Rio
14
Padrões relacionados
v Iterator
‒  Memento pode ser usado dentre suas iterações
v Command
‒  Podem usar Memento para manter o estado de
operações que podem ser desfeitas
11/09/2013
@LES/PUC-Rio
15
Referências bibliográficas
•  GAMMA, Erich; HELM, Richard; JOHNSON,
Ralph; VLISSIDES, John. Design Patterns:
Elements of Reusable Object-Oriented
Software.
•  Wikipedia – Memento Pattern http://en.wikipedia.org/wiki/
Memento_pattern
[acessado em 08/09/2013]
11/09/2013
@LES/PUC-Rio
16
Download