Java/Design Pattern/Memento Pattern
Версия от 18:01, 31 мая 2010; (обсуждение)
Memento Pattern 2
//[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();
}
}
Memento pattern in 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;
}
}