Java/Design Pattern/Memento Pattern
Memento Pattern 2
<source lang="java">
//[C] 2002 Sun Microsystems, Inc.--- import java.io.Serializable; import java.util.ArrayList; public class RunMementoPattern {
public static void main(String[] arguments) { System.out.println("Example for the Memento pattern"); System.out.println(); System.out .println("This example will use the AddressBook to demonstrate"); System.out .println(" how a Memento can be used to save and restore state."); System.out .println("The AddressBook has an inner class, AddressBookMemento,"); System.out .println(" that is used to store the AddressBook state... in this"); System.out.println(" case, its internal list of contacts."); System.out.println(); System.out.println("Creating the AddressBook"); AddressBook book = new AddressBook(); System.out.println("Adding Contact entries for the AddressBook"); book.addContact(new ContactImpl("Peter", "Taggart", "Commander", "NSEA Protector", new AddressImpl())); book.addContact(new ContactImpl("Tawny", "Madison", "Lieutenant", "NSEA Protector", new AddressImpl())); book.addContact(new ContactImpl("Dr.", "Lazarus", "Dr.", "NSEA Protector", new AddressImpl())); book.addContact(new ContactImpl("Tech Sargent", "Chen", "Tech Sargent", "NSEA Protector", new AddressImpl())); System.out.println("Contacts added. Current Contact list:"); System.out.println(book); System.out.println(); System.out.println("Creating a Memento for the address book"); Object memento = book.getMemento(); System.out .println("Now that a Memento exists, it can be used to restore"); System.out .println(" the state of this AddressBook object, or to set the"); System.out.println(" state of a new AddressBook."); System.out.println(); System.out.println("Creating new entries for the AddressBook"); book.removeAllContacts(); book.addContact(new ContactImpl("Jason", "Nesmith", "", "Actor"s Guild", new AddressImpl())); book.addContact(new ContactImpl("Gwen", "DeMarco", "", "Actor"s Guild", new AddressImpl())); book.addContact(new ContactImpl("Alexander", "Dane", "", "Actor"s Guild", new AddressImpl())); book.addContact(new ContactImpl("Fred", "Kwan", "", "Actor"s Guild", new AddressImpl())); System.out.println("New Contacts added. Current Contact list:"); System.out.println(book); System.out.println(); System.out .println("Using the Memento object to restore the AddressBook"); System.out.println(" to its original state."); book.setMemento(memento); System.out.println("AddressBook restored. Current Contact list:"); System.out.println(book); }
} interface Contact extends Serializable {
public static final String SPACE = " "; public String getFirstName(); public String getLastName(); public String getTitle(); public String getOrganization(); public void setFirstName(String newFirstName); public void setLastName(String newLastName); public void setTitle(String newTitle); public void setOrganization(String newOrganization);
} interface Address extends Serializable {
public static final String EOL_STRING = System .getProperty("line.separator"); public static final String SPACE = " "; public static final String COMMA = ","; public String getType(); public String getDescription(); public String getStreet(); public String getCity(); public String getState(); public String getZipCode(); public void setType(String newType); public void setDescription(String newDescription); public void setStreet(String newStreet); public void setCity(String newCity); public void setState(String newState); public void setZipCode(String newZip);
} class ContactImpl implements Contact {
private String firstName; private String lastName; private String title; private String organization; private Address address; public ContactImpl() { } public ContactImpl(String newFirstName, String newLastName, String newTitle, String newOrganization, Address newAddress) { firstName = newFirstName; lastName = newLastName; title = newTitle; organization = newOrganization; address = newAddress; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public String getTitle() { return title; } public String getOrganization() { return organization; } public Address getAddress() { return address; } public void setFirstName(String newFirstName) { firstName = newFirstName; } public void setLastName(String newLastName) { lastName = newLastName; } public void setTitle(String newTitle) { title = newTitle; } public void setOrganization(String newOrganization) { organization = newOrganization; } public void setAddress(Address newAddress) { address = newAddress; } public String toString() { return firstName + " " + lastName; }
} class AddressImpl implements Address {
private String type; private String description; private String street; private String city; private String state; private String zipCode; public AddressImpl() { } public AddressImpl(String newDescription, String newStreet, String newCity, String newState, String newZipCode) { description = newDescription; street = newStreet; city = newCity; state = newState; zipCode = newZipCode; } public String getType() { return type; } public String getDescription() { return description; } public String getStreet() { return street; } public String getCity() { return city; } public String getState() { return state; } public String getZipCode() { return zipCode; } public void setType(String newType) { type = newType; } public void setDescription(String newDescription) { description = newDescription; } public void setStreet(String newStreet) { street = newStreet; } public void setCity(String newCity) { city = newCity; } public void setState(String newState) { state = newState; } public void setZipCode(String newZip) { zipCode = newZip; } public String toString() { return street + EOL_STRING + city + COMMA + SPACE + state + SPACE + zipCode + EOL_STRING; }
} class AddressBook {
private ArrayList contacts = new ArrayList(); public Object getMemento() { return new AddressBookMemento(contacts); } public void setMemento(Object object) { if (object instanceof AddressBookMemento) { AddressBookMemento memento = (AddressBookMemento) object; contacts = memento.state; } } private class AddressBookMemento { private ArrayList state; private AddressBookMemento(ArrayList contacts) { this.state = contacts; } } public AddressBook() { } public AddressBook(ArrayList newContacts) { contacts = newContacts; } public void addContact(Contact contact) { if (!contacts.contains(contact)) { contacts.add(contact); } } public void removeContact(Contact contact) { contacts.remove(contact); } public void removeAllContacts() { contacts = new ArrayList(); } public ArrayList getContacts() { return contacts; } public String toString() { return contacts.toString(); }
}
</source>
Memento pattern in Java
<source lang="java">
/* The Design Patterns Java Companion Copyright (C) 1998, by James W. Cooper IBM Thomas J. Watson Research Center
- /
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Vector; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JToggleButton; import javax.swing.JToolBar; public class MemDraw extends JFrame implements ActionListener {
JToolBar tbar; Mediator med; public MemDraw() { super("Memento Drawing"); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); JPanel jp = new JPanel(); getContentPane().add(jp); med = new Mediator(); jp.setLayout(new BorderLayout()); tbar = new JToolBar(); jp.add("North", tbar); RectButton rect = new RectButton(this, med); tbar.add(rect); UndoButton undo = new UndoButton(this, med); tbar.add(undo); tbar.addSeparator(); ClearButton clr = new ClearButton(this, med); tbar.add(clr); JCanvas canvas = new JCanvas(med); jp.add("Center", canvas); MouseApp map = new MouseApp(med); canvas.addMouseListener(map); MouseMoveApp mvap = new MouseMoveApp(med); canvas.addMouseMotionListener(mvap); setSize(new Dimension(400, 300)); setVisible(true); } public void actionPerformed(ActionEvent e) { Command comd = (Command) e.getSource(); comd.Execute(); } static public void main(String[] argv) { new MemDraw(); }
} //============================== class MouseApp extends MouseAdapter {
Mediator med; public MouseApp(Mediator md) { super(); med = md; } public void mousePressed(MouseEvent e) { med.createRect(e.getX(), e.getY()); } public void mouseReleased(MouseEvent e) { med.rememberPosition(); }
}
class MouseMoveApp extends MouseMotionAdapter {
Mediator med; public MouseMoveApp(Mediator md) { super(); med = md; } public void mouseDragged(MouseEvent e) { med.drag(e.getX(), e.getY()); }
} class ClearButton extends JButton implements Command {
Mediator med; public ClearButton(ActionListener act, Mediator md) { super("C"); setToolTipText("Clear"); addActionListener(act); med = md; } public void Execute() { med.clear(); }
} class JCanvas extends JPanel {
Mediator med; public JCanvas(Mediator md) { med = md; med.registerCanvas(this); setBackground(Color.white); } public void paint(Graphics g) { super.paint(g); med.reDraw(g); }
} class Mediator {
boolean startRect; boolean rectSelected; Vector drawings; Vector undoList; RectButton rect; JPanel canvas; visRectangle selectedRectangle; public Mediator() { startRect = false; rectSelected = false; drawings = new Vector(); undoList = new Vector(); } public void startRectangle() { startRect = true; } public void createRect(int x, int y) { unpick(); //make sure no rectangle is selected if (startRect) //if rect button is depressed { Integer count = new Integer(drawings.size()); undoList.addElement(count); //Save previous drawing list size visRectangle v = new visRectangle(x, y); drawings.addElement(v); //add new element to list startRect = false; //done with this rectangle rect.setSelected(false); //unclick button canvas.repaint(); } else pickRect(x, y); //if not pressed look for rect to select } public void registerRectButton(RectButton rb) { rect = rb; } public void registerCanvas(JPanel p) { canvas = p; } private void unpick() { rectSelected = false; if (selectedRectangle != null) { selectedRectangle.setSelected(false); selectedRectangle = null; repaint(); } } public void rememberPosition() { if (rectSelected) { Memento m = new Memento(selectedRectangle); undoList.addElement(m); } } public void pickRect(int x, int y) { //save current selected rectangle to avoid double save of undo visRectangle lastPick = selectedRectangle; unpick(); for (int i = 0; i < drawings.size(); i++) { visRectangle v = (visRectangle) drawings.elementAt(i); if (v.contains(x, y)) //did click inside a rectangle { selectedRectangle = v; //save it rectSelected = true; if (selectedRectangle != lastPick) //but don"t save twice rememberPosition(); v.setSelected(true); //turn on handles repaint(); //and redraw } } } public void clear() { drawings = new Vector(); undoList = new Vector(); rectSelected = false; selectedRectangle = null; repaint(); } private void repaint() { canvas.repaint(); } public void drag(int x, int y) { if (rectSelected) { if (selectedRectangle.contains(x, y)) { selectedRectangle.move(x, y); repaint(); } } } public void reDraw(Graphics g) { g.setColor(Color.black); for (int i = 0; i < drawings.size(); i++) { visRectangle v = (visRectangle) drawings.elementAt(i); v.draw(g); } } public void undo() { if (undoList.size() > 0) { //get last element in undo list Object obj = undoList.lastElement(); undoList.removeElement(obj); //and remove it //if this is an Integer, the last action was a new rectangle if (obj instanceof Integer) { //remove last created rectangle Object drawObj = drawings.lastElement(); drawings.removeElement(drawObj); } //if this is a Memento, the last action was a move if (obj instanceof Memento) { //get the Memento Memento m = (Memento) obj; m.restore(); //and restore the old position } repaint(); } }
} interface Command {
public void Execute();
} class RectButton extends JToggleButton implements Command {
Mediator med; public RectButton(ActionListener act, Mediator md) { super("R"); //setSize(new Dimension(25,25)); //setBorder(new EmptyBorder(5,5,5,5)); setToolTipText("Draw rectangle"); addActionListener(act); med = md; med.registerRectButton(this); } public void Execute() { if (isSelected()) { med.startRectangle(); } }
} class UndoButton extends JButton implements Command {
Mediator med; public UndoButton(ActionListener act, Mediator md) { super("U"); //setSize(new Dimension(25,25)); //setBorder(new EmptyBorder(5,5,5,5)); setToolTipText("Undo"); addActionListener(act); med = md; } public void Execute() { med.undo(); }
} class visRectangle {
int x, y, w, h; Rectangle rect; boolean selected; public visRectangle(int xpt, int ypt) { x = xpt; y = ypt; w = 40; h = 30; saveAsRect(); } public void setSelected(boolean b) { selected = b; } private void saveAsRect() { rect = new Rectangle(x - w / 2, y - h / 2, w, h); } public void draw(Graphics g) { g.drawRect(x, y, w, h); if (selected) { g.fillRect(x + w / 2, y - 2, 4, 4); g.fillRect(x - 2, y + h / 2, 4, 4); g.fillRect(x + w / 2, y + h - 2, 4, 4); g.fillRect(x + w - 2, y + h / 2, 4, 4); } } public boolean contains(int x, int y) { return rect.contains(x, y); } public void move(int xpt, int ypt) { x = xpt; y = ypt; saveAsRect(); }
} //=============================================== class Memento {
visRectangle rect; //saved fields- remember internal fields //of the specified visual rectangle int x, y, w, h; public Memento(visRectangle r) { rect = r; x = rect.x; y = rect.y; w = rect.w; h = rect.h; } public void restore() { //restore the internal state of //the specified rectangle rect.x = x; rect.y = y; rect.h = h; rect.w = w; }
}
</source>