dcsimg
September 23, 2018
Hot Topics:

Working With Design Patterns: Memento

  • January 10, 2008
  • By Jeff Langr
  • Send Email »
  • More Articles »

When you undo a command, it needs to reset the state of the PathCanvas to a prior point in time. A stored Memento object represents this prior point. The method setMemento updates the state of the PathCanvas object.

Listing 4: PathCanvas.

import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import java.util.List;

public class PathCanvas extends Observable implements
   MementoOriginator, Displayable {
   private List<ColoredPath> paths =
      new ArrayList<ColoredPath>();

   public List<ColoredPath> paths() {
      return paths;
   }

   public void add(ColoredPath path) {
      paths.add(path);
      changed();
   }

   public void displayOn(Graphics2D graphics) {
      for (ColoredPath path: paths) {
         Area polygon = new Area(path.getGeneralPath());
         graphics.setColor(path.getColor());
         graphics.fill(polygon);
      }
   }

   public Memento getMemento() {
      List<ColoredPath> pathCopies =
         new ArrayList<ColoredPath>();
      pathCopies.addAll(paths);
      return new Memento(pathCopies);
   }

   @Override
   public void setMemento(Memento memento) {
      paths.clear();
      paths.addAll(memento.getPaths());
      changed();
   }

   private void changed() {
      setChanged();
      notifyObservers();
   }
}

I created the MementoOriginator interface not out of necessity, but to reinforce the class names used in the Design Patterns book. The interface is simply:

public interface MementoOriginator {
   Memento getMemento();
   void setMemento(Memento memento);
}

Listing 5: Memento.

import java.util.*;

public class Memento {
   private List<ColoredPath> paths;

   public Memento(List<ColoredPath> paths) {
      this.paths = paths;
   }

   public List<ColoredPath> getPaths() {
      return paths;
   }
}

The most involved piece of the puzzle is the set of commands themselves. I implemented TriangleCommand and SquareCommand to demonstrate drawing a couple different shapes. Because each command needs to support being executed, undone, and redone, I was able to move some commonality into a superclass AbstractCommand (see Listing 6).

Listing 6: AbstractCommand.

import java.awt.*;
import java.util.*;
import model.*;
import model.PathCanvas;

import commandframework.*;

abstract public class AbstractCommand implements Command {
   private Memento memento;

   private Random random = new Random();
   protected double width;
   protected double height;
   protected PathCanvas canvas;
   protected Color color;

   public AbstractCommand() {
   }

   public AbstractCommand(PathCanvas canvas, double width,
      double height, Color color) {
      this.width = width;
      this.height = height;
      this.canvas = canvas;
      this.color = color;
   }

   public void execute() {
      this.memento = canvas.getMemento();
      transform();
   }

   abstract protected void transform();

   public void undo() {
      Memento redoMemento = canvas.getMemento();
      canvas.setMemento(memento);
      memento = redoMemento;
   }

   public void redo() {
      Memento undoMemento = canvas.getMemento();
      canvas.setMemento(memento);
      memento = undoMemento;
   }

   protected double random(double max) {
      return random.nextDouble() * max;
   }
}




Page 2 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

By submitting your information, you agree that developer.com may send you developer offers via email, phone and text message, as well as email offers about other products and services that developer believes may be of interest to you. developer will process your information in accordance with the Quinstreet Privacy Policy.

Sitemap

Thanks for your registration, follow us on our social networks to keep up-to-date