Java/Design Pattern/State Pattern

Материал из Java эксперт
Перейти к: навигация, поиск

Dynamically changing the behavior of an object via composition (the State design pattern)

   <source lang="java">

// : c07:Transmogrify.java // Dynamically changing the behavior of an object via composition (the State design pattern). // From "Thinking in Java, 3rd ed." (c) Bruce Eckel 2002 // www.BruceEckel.ru. See copyright notice in CopyRight.txt. abstract class Actor {

 public abstract void act();

} class HappyActor extends Actor {

 public void act() {
   System.out.println("HappyActor");
 }

} class SadActor extends Actor {

 public void act() {
   System.out.println("SadActor");
 }

} class Stage {

 private Actor actor = new HappyActor();
 public void change() {
   actor = new SadActor();
 }
 public void performPlay() {
   actor.act();
 }

} public class Transmogrify {

 public static void main(String[] args) {
   Stage stage = new Stage();
   stage.performPlay();
   stage.change();
   stage.performPlay();
 }

} ///:~


      </source>
   
  
 
  



State Pattern in Java

   <source lang="java">

//[C] 2002 Sun Microsystems, Inc.--- import java.awt.BorderLayout; import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.AbstractTableModel; public class RunStatePattern {

 public static void main(String[] arguments) {
   System.out.println("Example for the State pattern");
   System.out.println();
   if (!(new File("appointments.ser").exists())) {
     DataCreator.serialize("appointments.ser");
   }
   System.out.println("Creating CalendarEditor");
   CalendarEditor appointmentBook = new CalendarEditor();
   System.out.println("");
   System.out.println("Created. Appointments:");
   System.out.println(appointmentBook.getAppointments());
   System.out.println("Created. Creating GUI:");
   StateGui application = new StateGui(appointmentBook);
   application.createGui();
   System.out.println("");
 }

} interface State {

 public void save();
 public void edit();

} 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);

} class ContactImpl implements Contact {

 private String firstName;
 private String lastName;
 private String title;
 private String organization;
 public ContactImpl() {
 }
 public ContactImpl(String newFirstName, String newLastName,
     String newTitle, String newOrganization) {
   firstName = newFirstName;
   lastName = newLastName;
   title = newTitle;
   organization = newOrganization;
 }
 public String getFirstName() {
   return firstName;
 }
 public String getLastName() {
   return lastName;
 }
 public String getTitle() {
   return title;
 }
 public String getOrganization() {
   return organization;
 }
 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 String toString() {
   return firstName + SPACE + lastName;
 }

} interface Location extends Serializable {

 public String getLocation();
 public void setLocation(String newLocation);

} class LocationImpl implements Location {

 private String location;
 public LocationImpl() {
 }
 public LocationImpl(String newLocation) {
   location = newLocation;
 }
 public String getLocation() {
   return location;
 }
 public void setLocation(String newLocation) {
   location = newLocation;
 }
 public String toString() {
   return location;
 }

} class FileLoader {

 public static Object loadData(File inputFile) {
   Object returnValue = null;
   try {
     if (inputFile.exists()) {
       if (inputFile.isFile()) {
         ObjectInputStream readIn = new ObjectInputStream(
             new FileInputStream(inputFile));
         returnValue = readIn.readObject();
         readIn.close();
       } else {
         System.err.println(inputFile + " is a directory.");
       }
     } else {
       System.err.println("File " + inputFile + " does not exist.");
     }
   } catch (ClassNotFoundException exc) {
     exc.printStackTrace();
   } catch (IOException exc) {
     exc.printStackTrace();
   }
   return returnValue;
 }
 public static void storeData(File outputFile, Serializable data) {
   try {
     ObjectOutputStream writeOut = new ObjectOutputStream(
         new FileOutputStream(outputFile));
     writeOut.writeObject(data);
     writeOut.close();
   } catch (IOException exc) {
     exc.printStackTrace();
   }
 }

} class DataCreator {

 private static final String DEFAULT_FILE = "data.ser";
 private static Calendar dateCreator = Calendar.getInstance();
 public static void main(String[] args) {
   String fileName;
   if (args.length == 1) {
     fileName = args[0];
   } else {
     fileName = DEFAULT_FILE;
   }
   serialize(fileName);
 }
 public static void serialize(String fileName) {
   try {
     serializeToFile(createData(), fileName);
   } catch (IOException exc) {
     exc.printStackTrace();
   }
 }
 private static Serializable createData() {
   ArrayList appointments = new ArrayList();
   ArrayList contacts = new ArrayList();
   contacts.add(new ContactImpl("Test", "Subject", "Volunteer",
       "United Patterns Consortium"));
   Location location1 = new LocationImpl("Punxsutawney, PA");
   appointments.add(new Appointment("Slowpokes anonymous", contacts,
       location1, createDate(2001, 1, 1, 12, 01), createDate(2001, 1,
           1, 12, 02)));
   appointments.add(new Appointment("Java focus group", contacts,
       location1, createDate(2001, 1, 1, 12, 30), createDate(2001, 1,
           1, 14, 30)));
   appointments
       .add(new Appointment("Something else", contacts, location1,
           createDate(2001, 1, 1, 12, 01), createDate(2001, 1, 1,
               12, 02)));
   appointments.add(new Appointment("Yet another thingie", contacts,
       location1, createDate(2001, 1, 1, 12, 01), createDate(2001, 1,
           1, 12, 02)));
   return appointments;
 }
 private static void serializeToFile(Serializable content, String fileName)
     throws IOException {
   ObjectOutputStream serOut = new ObjectOutputStream(
       new FileOutputStream(fileName));
   serOut.writeObject(content);
   serOut.close();
 }
 public static Date createDate(int year, int month, int day, int hour,
     int minute) {
   dateCreator.set(year, month, day, hour, minute);
   return dateCreator.getTime();
 }

} class Appointment implements Serializable {

 private String reason;
 private ArrayList contacts;
 private Location location;
 private Date startDate;
 private Date endDate;
 public Appointment(String reason, ArrayList contacts, Location location,
     Date startDate, Date endDate) {
   this.reason = reason;
   this.contacts = contacts;
   this.location = location;
   this.startDate = startDate;
   this.endDate = endDate;
 }
 public String getReason() {
   return reason;
 }
 public ArrayList getContacts() {
   return contacts;
 }
 public Location getLocation() {
   return location;
 }
 public Date getStartDate() {
   return startDate;
 }
 public Date getEndDate() {
   return endDate;
 }
 public void setReason(String reason) {
   this.reason = reason;
 }
 public void setContacts(ArrayList contacts) {
   this.contacts = contacts;
 }
 public void setLocation(Location location) {
   this.location = location;
 }
 public void setStartDate(Date startDate) {
   this.startDate = startDate;
 }
 public void setEndDate(Date endDate) {
   this.endDate = endDate;
 }
 public String toString() {
   return "Appointment:" + "\n    Reason: " + reason + "\n    Location: "
       + location + "\n    Start: " + startDate + "\n    End: "
       + endDate + "\n";
 }

} class CalendarEditor {

 private State currentState;
 private File appointmentFile;
 private ArrayList appointments = new ArrayList();
 private static final String DEFAULT_APPOINTMENT_FILE = "appointments.ser";
 public CalendarEditor() {
   this(DEFAULT_APPOINTMENT_FILE);
 }
 public CalendarEditor(String appointmentFileName) {
   appointmentFile = new File(appointmentFileName);
   try {
     appointments = (ArrayList) FileLoader.loadData(appointmentFile);
   } catch (ClassCastException exc) {
     System.err
         .println("Unable to load information. The file does not contain a list of appointments.");
   }
   currentState = new CleanState();
 }
 public void save() {
   currentState.save();
 }
 public void edit() {
   currentState.edit();
 }
 private class DirtyState implements State {
   private State nextState;
   public DirtyState(State nextState) {
     this.nextState = nextState;
   }
   public void save() {
     FileLoader.storeData(appointmentFile, appointments);
     currentState = nextState;
   }
   public void edit() {
   }
 }
 private class CleanState implements State {
   private State nextState = new DirtyState(this);
   public void save() {
   }
   public void edit() {
     currentState = nextState;
   }
 }
 public ArrayList getAppointments() {
   return appointments;
 }
 public void addAppointment(Appointment appointment) {
   if (!appointments.contains(appointment)) {
     appointments.add(appointment);
   }
 }
 public void removeAppointment(Appointment appointment) {
   appointments.remove(appointment);
 }

} class StateGui implements ActionListener {

 private JFrame mainFrame;
 private JPanel controlPanel, editPanel;
 private CalendarEditor editor;
 private JButton save, exit;
 public StateGui(CalendarEditor edit) {
   editor = edit;
 }
 public void createGui() {
   mainFrame = new JFrame("State Pattern Example");
   Container content = mainFrame.getContentPane();
   content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
   editPanel = new JPanel();
   editPanel.setLayout(new BorderLayout());
   JTable appointmentTable = new JTable(new StateTableModel(
       (Appointment[]) editor.getAppointments().toArray(
           new Appointment[1])));
   editPanel.add(new JScrollPane(appointmentTable));
   content.add(editPanel);
   controlPanel = new JPanel();
   save = new JButton("Save Appointments");
   exit = new JButton("Exit");
   controlPanel.add(save);
   controlPanel.add(exit);
   content.add(controlPanel);
   save.addActionListener(this);
   exit.addActionListener(this);
   mainFrame.addWindowListener(new WindowCloseManager());
   mainFrame.pack();
   mainFrame.setVisible(true);
 }
 public void actionPerformed(ActionEvent evt) {
   Object originator = evt.getSource();
   if (originator == save) {
     saveAppointments();
   } else if (originator == exit) {
     exitApplication();
   }
 }
 private class WindowCloseManager extends WindowAdapter {
   public void windowClosing(WindowEvent evt) {
     exitApplication();
   }
 }
 private void saveAppointments() {
   editor.save();
 }
 private void exitApplication() {
   System.exit(0);
 }
 private class StateTableModel extends AbstractTableModel {
   private final String[] columnNames = { "Appointment", "Contacts",
       "Location", "Start Date", "End Date" };
   private Appointment[] data;
   public StateTableModel(Appointment[] appointments) {
     data = appointments;
   }
   public String getColumnName(int column) {
     return columnNames[column];
   }
   public int getRowCount() {
     return data.length;
   }
   public int getColumnCount() {
     return columnNames.length;
   }
   public Object getValueAt(int row, int column) {
     Object value = null;
     switch (column) {
     case 0:
       value = data[row].getReason();
       break;
     case 1:
       value = data[row].getContacts();
       break;
     case 2:
       value = data[row].getLocation();
       break;
     case 3:
       value = data[row].getStartDate();
       break;
     case 4:
       value = data[row].getEndDate();
       break;
     }
     return value;
   }
   public boolean isCellEditable(int row, int column) {
     return ((column == 0) || (column == 2)) ? true : false;
   }
   public void setValueAt(Object value, int row, int column) {
     switch (column) {
     case 0:
       data[row].setReason((String) value);
       editor.edit();
       break;
     case 1:
       break;
     case 2:
       data[row].setLocation(new LocationImpl((String) value));
       editor.edit();
       break;
     case 3:
       break;
     case 4:
       break;
     }
   }
 }

}


      </source>
   
  
 
  



State pattern in Java 2

   <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.Insets; 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.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JToggleButton; import javax.swing.JToolBar; public class StateDraw extends JFrame implements ActionListener {

 JToolBar tbar;
 Mediator med;
 public StateDraw() {
   super("State 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();
   tbar.setFloatable(false);
   jp.add("North", tbar);
   PickButton pick = new PickButton(this, med);
   tbar.add(pick);
   tbar.addSeparator();
   RectButton rect = new RectButton(this, med);
   tbar.add(rect);
   FillButton fill = new FillButton(this, med);
   tbar.add(fill);
   CircleButton circ = new CircleButton(this, med);
   tbar.add(circ);
   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 StateDraw();
 }

}

class MouseApp extends MouseAdapter {

 Mediator med;
 public MouseApp(Mediator md) {
   super();
   med = md;
 }
 public void mousePressed(MouseEvent e) {
   med.mouseDown(e.getX(), e.getY());
 }
 public void mouseReleased(MouseEvent e) {
   med.mouseUp(e.getX(), e.getY());
 }

} class MouseMoveApp extends MouseMotionAdapter {

 Mediator med;
 public MouseMoveApp(Mediator md) {
   super();
   med = md;
 }
 public void mouseDragged(MouseEvent e) {
   med.mouseDrag(e.getX(), e.getY());
 }

} class ArrowState extends State {

 private Mediator med;
 public ArrowState(Mediator md) {
   med = md;
 }
 public void mouseDown(int x, int y) {
   Vector drawings = med.getDrawings();
   for (int i = 0; i < drawings.size(); i++) {
     Drawing d = (Drawing) drawings.elementAt(i);
     if (d.contains(x, y))
       med.setSelected(d);
   }
 }

} class CircleState extends State {

 private Mediator med; //save Mediator
 public CircleState(Mediator md) {
   med = md;
 }
 //Draw circle where mouse clicks
 public void mouseDown(int x, int y) {
   med.addDrawing(new visCircle(x, y));
 }

} 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 CircleButton extends JToggleButton implements Command {

 Mediator med;
 public CircleButton(ActionListener act, Mediator md) {
   super(" ");
   setSize(new Dimension(35, 35));
   setBorderPainted(true);
   setMargin(new Insets(5, 12, 5, 12));
   setToolTipText("Draw circle");
   addActionListener(act);
   med = md;
   med.registerCircleButton(this);
 }
 public Dimension getPreferredSize() {
   return new Dimension(35, 35);
 }
 public void paint(Graphics g) {
   super.paint(g);
   int h = getHeight();
   int w = getWidth();
   g.setColor(Color.black);
   g.drawArc(2, 2, h - 4, h - 4, 0, 360);
 }
 public void Execute() {
   med.startCircle();
 }

} class State {

 public void mouseDown(int x, int y) {
 }
 public void mouseUp(int x, int y) {
 }
 public void mouseDrag(int x, int y) {
 }
 public void select(Drawing d, Color c) {
 }

} interface Command {

 public void Execute();

} class FillState extends State {

 private Mediator med; //save Mediator
 private Color color; //save current color
 public FillState(Mediator md) {
   med = md;
 }
 //Fill drawing if selected
 public void select(Drawing d, Color c) {
   color = c;
   if (d != null) {
     d.setFill(c); //fill that drawing
   }
 }
 //Fill drawing if you click inside one
 public void mouseDown(int x, int y) {
   Vector drawings = med.getDrawings();
   for (int i = 0; i < drawings.size(); i++) {
     Drawing d = (Drawing) drawings.elementAt(i);
     if (d.contains(x, y))
       d.setFill(color); //fill drawing
   }
 }

} 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 dSelected;
 Vector drawings;
 Vector undoList;
 RectButton rectButton;
 FillButton fillButton;
 CircleButton circButton;
 PickButton arrowButton;
 JPanel canvas;
 Drawing selectedDrawing;
 StateManager stMgr;
 public Mediator() {
   startRect = false;
   dSelected = false;
   drawings = new Vector();
   undoList = new Vector();
   stMgr = new StateManager(this);
 }
 public void startRectangle() {
   stMgr.setRect();
   arrowButton.setSelected(false);
   circButton.setSelected(false);
   fillButton.setSelected(false);
 }
 public void startCircle() {
   stMgr.setCircle();
   rectButton.setSelected(false);
   arrowButton.setSelected(false);
   fillButton.setSelected(false);
 }
 public void startFill() {
   stMgr.setFill();
   rectButton.setSelected(false);
   circButton.setSelected(false);
   arrowButton.setSelected(false);
   stMgr.select(selectedDrawing, Color.red);
   repaint();
 }
 public void startArrow() {
   stMgr.setArrow();
   rectButton.setSelected(false);
   circButton.setSelected(false);
   fillButton.setSelected(false);
 }
 public Drawing getSelected() {
   return selectedDrawing;
 }
 public void fillSelected() {
   if (dSelected) {
     selectedDrawing.setFill(Color.red);
   }
 }
 public Vector getDrawings() {
   return drawings;
 }
 public void addDrawing(Drawing d) {
   drawings.addElement(d);
 }
 public void registerRectButton(RectButton rb) {
   rectButton = rb;
 }
 public void registerCircleButton(CircleButton cb) {
   circButton = cb;
 }
 public void registerArrowButton(PickButton ab) {
   arrowButton = ab;
 }
 public void registerFillButton(FillButton fb) {
   fillButton = fb;
 }
 public void registerCanvas(JPanel p) {
   canvas = p;
 }
 public void mouseDown(int x, int y) {
   stMgr.mouseDown(x, y);
   repaint();
 }
 public void mouseUp(int x, int y) {
   stMgr.mouseUp(x, y);
 }
 public void unpick() {
   dSelected = false;
   if (selectedDrawing != null) {
     selectedDrawing.setSelected(false);
     selectedDrawing = null;
     repaint();
   }
 }
 public void rememberPosition() {
   if (dSelected) {
     //Memento m = new Memento(d);
     //undoList.addElement(m);
   }
 }
 public void setSelected(Drawing d) {
   if (d != null) {
     dSelected = true;
     selectedDrawing = d;
     d.setSelected(true);
     repaint();
   }
 }
 public void pickRect(int x, int y) {
 }
 public void clear() {
   drawings = new Vector();
   undoList = new Vector();
   dSelected = false;
   selectedDrawing = null;
   repaint();
 }
 private void repaint() {
   canvas.repaint();
 }
 public void mouseDrag(int x, int y) {
   stMgr.mouseDrag(x, y);
 }
 public void reDraw(Graphics g) {
   g.setColor(Color.black);
   for (int i = 0; i < drawings.size(); i++) {
     Drawing v = (Drawing) 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();
   }
 }

} class RectButton extends JToggleButton implements Command {

 Mediator med;
 public RectButton(ActionListener act, Mediator md) {
   super(" ");
   setSize(new Dimension(35, 35));
   setBorderPainted(true);
   setMargin(new Insets(5, 12, 5, 12));
   setToolTipText("Draw rectangle");
   addActionListener(act);
   med = md;
   med.registerRectButton(this);
 }
 public Dimension getPreferredSize() {
   return new Dimension(35, 35);
 }
 public void paint(Graphics g) {
   super.paint(g);
   int h = getHeight();
   int w = getWidth();
   g.setColor(Color.black);
   g.drawRect(4, 4, w - 8, h - 8);
 }
 public void Execute() {
   med.startRectangle();
 }

} class UndoButton extends JButton implements Command {

 Mediator med;
 public UndoButton(ActionListener act, Mediator md) {
   super("U");
   //setSize(new Dimension(25,25));
   setMargin(new Insets(5, 12, 5, 12));
   setToolTipText("Undo");
   addActionListener(act);
   med = md;
 }
 public void Execute() {
   med.undo();
 }

} class FillButton extends JToggleButton implements Command {

 Mediator med;
 public FillButton(ActionListener act, Mediator md) {
   super(" ");
   setSize(new Dimension(35, 35));
   setBorderPainted(true);
   setMargin(new Insets(5, 12, 5, 12));
   setToolTipText("Fill rectangle");
   addActionListener(act);
   med = md;
   med.registerFillButton(this);
 }
 public Dimension getPreferredSize() {
   return new Dimension(35, 35);
 }
 public void paint(Graphics g) {
   super.paint(g);
   int h = getHeight();
   int w = getWidth();
   g.setColor(Color.black);
   g.drawRect(4, 4, w - 8, h - 8);
   g.setColor(Color.red);
   g.fillRect(4, 10, w - 8, h - 14);
 }
 public void Execute() {
   if (isSelected()) {
     med.startFill();
   }
 }

} class Memento {

 public Memento(Drawing d) {
 }
 public void restore() {
 }

} class RectState extends State {

 private Mediator med; //save the Mediator here
 public RectState(Mediator md) {
   med = md;
 }
 //create a new Rectangle where mode clicks
 public void mouseDown(int x, int y) {
   med.addDrawing(new visRectangle(x, y));
 }

} class StateManager {

 private State currentState;
 RectState rState;
 ArrowState aState;
 CircleState cState;
 FillState fState;
 public StateManager(Mediator med) {
   rState = new RectState(med);
   cState = new CircleState(med);
   aState = new ArrowState(med);
   fState = new FillState(med);
   currentState = aState;
 }
 public void setRect() {
   currentState = rState;
 }
 public void setCircle() {
   currentState = cState;
 }
 public void setFill() {
   currentState = fState;
 }
 public void setArrow() {
   currentState = aState;
 }
 public void mouseDown(int x, int y) {
   currentState.mouseDown(x, y);
 }
 public void mouseUp(int x, int y) {
   currentState.mouseUp(x, y);
 }
 public void mouseDrag(int x, int y) {
   currentState.mouseDrag(x, y);
 }
 public void select(Drawing d, Color c) {
   currentState.select(d, c);
 }

} class Drawing {

 protected int x, y, w, h;
 protected Rectangle rect;
 protected boolean selected;
 protected boolean filled;
 protected Color fillColor;
 //-------------------------------------------
 public void setSelected(boolean b) {
   selected = b;
 }
 public void draw(Graphics g) {
 }
 public void move(int xpt, int ypt) {
   x = xpt;
   y = ypt;
 }
 public boolean contains(int x, int y) {
   return rect.contains(x, y);
 }
 protected void saveAsRect() {
   rect = new Rectangle(x - w / 2, y - h / 2, w, h);
 }
 protected void setFill(Color c) {
   filled = true;
   fillColor = c;
 }

} class visCircle extends Drawing {

 public visCircle(int xpt, int ypt) {
   x = xpt;
   y = ypt;
   w = 40;
   h = 30;
   saveAsRect();
 }
 //-------------------------------------------
 public void draw(Graphics g) {
   g.drawArc(x, y, w, h, 0, 360);
   if (filled) {
     g.setColor(fillColor);
     g.fillArc(x, y, w, h, 0, 360);
   }
   if (selected) {
     g.setColor(Color.black);
     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);
   }
 }

} //=============================================== class circleMemento extends Memento {

 visCircle circ;
 //saved fields- remember internal fields
 //of the specified visual rectangle
 int x, y, w, h;
 public circleMemento(visCircle r) {
   super(r);
   circ = r;
   x = circ.x;
   y = circ.y;
   w = circ.w;
   h = circ.h;
 }
 //-------------------------------------------
 public void restore() {
   //restore the internal state of
   //the specified rectangle
   circ.x = x;
   circ.y = y;
   circ.h = h;
   circ.w = w;
 }

} class visRectangle extends Drawing {

 public visRectangle(int xpt, int ypt) {
   x = xpt;
   y = ypt;
   w = 40;
   h = 30;
   saveAsRect();
 }
 //-------------------------------------------
 public void draw(Graphics g) {
   g.drawRect(x, y, w, h);
   if (filled) {
     g.setColor(fillColor);
     g.fillRect(x, y, w, h);
   }
   if (selected) {
     g.setColor(Color.black);
     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);
   }
 }

}

class rectMemento extends Memento {

 visRectangle rect;
 //saved fields- remember internal fields
 //of the specified visual rectangle
 int x, y, w, h;
 public rectMemento(visRectangle r) {
   super(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;
 }

} class PickButton extends JToggleButton implements Command {

 Mediator med;
 public PickButton(ActionListener act, Mediator md) {
   super(new ImageIcon("arrow.gif"));
   setSize(new Dimension(35, 35));
   setBorderPainted(true);
   setMargin(new Insets(0, 0, 0, 0));
   setToolTipText("Select drawing element");
   addActionListener(act);
   med = md;
   med.registerArrowButton(this);
 }
 //-------------------------------------------
 public void Execute() {
   med.startArrow();
 }

}


      </source>