Estou precisando muito da ajuda do GUJ!!!
Eu quero poder desfazer as minhas ações em um programa. Para isso, uso o padrão Memento. O programa é simples. Toda vez que clico em calcular, uma cópia do objeto atual é clonado pelo padrão prototype e salvo em uma lista. Quando eu clico em recuperar uma vez, a lista é percorrida uma vez e o último clone salvo nela é removido. O problema é que, pelos meus testes, todas as cópias que jogo na lista apontam para o mesmo objeto e não deveria ser assim, já que clono antes de jogar na lista.
Peço, por favor, que me ajudem. O programa parece grande, mas só preciso saber por que o mesmo objeto está sendo salvo na lista ao invés de clones dele. Se quiserem testar, é só copiar e colar que funciona sem problemas! Vou postar o código e explicando…
Essa é a classe Originador. Essa classe pede para fazer uma cópia de um objeto. Na linha 63, CallMementoFromOriginador() invoca nas linhas 93 e 94 a classe PrototypeFactory, que é um padrão Prototype. Nessa classe, uma cópia do objeto Originador é salvo. Há ainda nessa classe um método getClone() que retorna a cópia. Essa classe é mostrada em seguida.
package gof.comportamental.memento;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
public class Originador extends JFrame implements Cloneable{
/**
*
*/
private static final long serialVersionUID = 1L;
private JLabel valor1, valor2, resultado;
private JButton calcular, desfazer;
private JTextField campo1, campo2, camporesultado;
private FlowLayout flowlayout;
public Originador(){
valor1 = new JLabel("Valor 1");
valor2 = new JLabel("Valor 2");
resultado = new JLabel("Resultado");
campo1 = new JTextField(3);
campo2 = new JTextField(3);
camporesultado = new JTextField(3);
calcular = new JButton("Calcular");
desfazer = new JButton("Desfazer");
flowlayout = new FlowLayout();
this.setLayout(flowlayout);
this.add(valor1);
this.add(campo1);
this.add(valor2);
this.add(campo2);
this.add(resultado);
this.add(camporesultado);
this.add(calcular);
this.add(desfazer);
calcular.addActionListener
(
new ActionListener()
{
public void actionPerformed( ActionEvent e )
{
if( e.getSource() == calcular )
{
getCamporesultado().setText(String.valueOf(
Integer.parseInt(getCampo1().getText())+
Integer.parseInt(getCampo2().getText())));
//Chama a classe Memento para salvar um estado do objeto.
try{
CallMementoFromOriginador();
}
catch(CloneNotSupportedException ex){
ex.printStackTrace();
}
}
}
}
);
desfazer.addActionListener
(
new ActionListener()
{
public void actionPerformed( ActionEvent e )
{
if( e.getSource() == desfazer )
{
Memento.getInstance().getState();
}
}
}
);
}
public void CallMementoFromOriginador() throws CloneNotSupportedException{
PrototypeFactory prototypefactory = new PrototypeFactory(this);
Memento.getInstance().setState(prototypefactory.getClone());
}
public JTextField getCampo1() {
return campo1;
}
public JTextField getCampo2() {
return campo2;
}
public JTextField getCamporesultado() {
return camporesultado;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
public static void main(String []args){
Originador originador = new Originador();
originador.setSize(230, 130);
originador.setVisible(true);
originador.setLocationRelativeTo(null);
originador.setResizable(false);
originador.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Classe PrototypeFactory, que cria cópias do objeto Originador.
package gof.comportamental.memento;
public class PrototypeFactory {
private Originador originador;
//Cria um clone.
public PrototypeFactory(Originador originador){
this.originador = originador;
}
//Retorna um clone.
public Originador getClone() throws CloneNotSupportedException{
return (Originador)originador.clone();
}
}
Essa é a classe Memento, que guarda em uma lista os objetos clonados de Originador e os recupera. Essa classe usa o padrão Singleton, mas não tem problemas, pois quero apena uma lista e um objeto Memento salvando e recuperando.
package gof.comportamental.memento;
import java.util.ArrayList;
import java.util.List;
public class Memento {
private static final Memento instancia = new Memento();
private static List<Originador> lista = new ArrayList<Originador>();
private Memento(){}
public static Memento getInstance(){
return instancia;
}
//recupera o valor do objeto quando pedido
public void getState(){
if(!this.getLista().isEmpty()){
System.out.println(getLista().remove(getLista().size()-1).getCamporesultado().getText());
}
}
//Salva o estado do objeto para posterior recuperação.
public void setState(Originador originador){
lista.add(originador);
}
public List<Originador> getLista(){
return lista;
}
}
O programa simula um ctrl+z. Entrem com valores nos campos e precionem Calcular. Nessa hora, uma cópia do objeto é salvo automaticamente. Entrem novamente com valores e cliquem em Calcular. A mesma coisa acontece. Ao clicar em Desfazer, deveria aparecer o resultado da primeira conta no console mas, ao invés, aparece o da segunda conta. Aí que ví que o mesmo objeto está sendo guardado mais de uma vez na lista.
Agradeço desde já!