Etcher-Sketcher
An Example of the Observer Pattern |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
PointSubject
/** * A subject (in the sense of the oberver pattern) that generates * Point objects * * @author Prof. David Bernstein, James Madison University * @version 1.0 */ public interface PointSubject { /** * Add a PointObserver to the list of existing observers * * @param observer The PointObserver to add */ public abstract void addPointObserver(PointObserver observer); /** * Notify all observers of a Point "event" * * @param p The Point to notify the observers about */ public abstract void notifyPointObservers(Point p); /** * Remove a PointObserver from the list of existing observers * * @param observer The PointObserver to remove */ public abstract void removePointObserver(PointObserver observer); }
PointObserver
/** * An observer (in the sense of the oberver pattern) that wants to * be informed of Point "events" * * @author Prof. David Bernstein, James Madison University * @version 1.0 */ public interface PointObserver { /** * Handle a Point "event" * * @param subject The PointSubject that generated the Point * @param p The Point of interest */ public abstract void handlePoint(PointSubject subject, Point p); }
WayIconSubject
import java.util.*; /** * A PointSubject that generates a sequence of Point objects * in the shape of the Way icon * * @author Prof. David Bernstein, James Madison University * @version 1.0 */ public class WayIconSubject implements Runnable, PointSubject { private Hashtable observers; private Thread controlThread; private Vector points; /** * Default Constructor */ public WayIconSubject() { controlThread = new Thread(this); observers = new Hashtable(); // Define the points points = new Vector(); for (double x=70; x<=140; x++) addPoint(x, 140); for (double y=140;y<=170; y++) addPoint(140, y); for (double d=0; d<=80; d++) addPoint(140+d, 170-d); for (double d=0; d<=80; d++) addPoint(220-d, 90-d); for (double y=10;y<=40; y++) addPoint(140, y); for (double x=140; x>=50; x--) addPoint(x, 40); for (double d=0; d<=100; d++) addPoint(50+d/5,40+d); } /** * A utility method for adding a Point to the * (pre-defined) collection of Point "events" * * @param x The horizontal coordinate * @param y The vertical coordinate */ private void addPoint(double x, double y) { double[] v; v = new double[2]; v[0] = x; v[1] = y; points.add(new Point(v)); } /** * Add a PointObserver to the list of existing observers * (required by PointSubject) * * @param observer The PointObserver to add */ public void addPointObserver(PointObserver observer) { observers.put(observer, observer); } /** * Notify all observers of a Point "event" * (required by PointSubject) * * @param p The Point to notify the observers about */ public void notifyPointObservers(Point p) { Enumeration e; PointObserver observer; e = observers.elements(); while (e.hasMoreElements()) { observer = (PointObserver)e.nextElement(); observer.handlePoint(this, p); } } /** * Remove a PointObserver from the list of existing observers * (required by PointSubject) * * @param observer The PointObserver to remove */ public void removePointObserver(PointObserver observer) { observers.remove(observer); } /** * The code to execute (required by Runnable) * * Specifically, inform all observers of the sequence of * Point "events" */ public void run() { Enumeration e; Point p; e = points.elements(); while (e.hasMoreElements()) { p = (Point)e.nextElement(); notifyPointObservers(p); try { controlThread.sleep(10); } catch (InterruptedException ie) { // Ignore } } } /** * Start the new thread of execution */ public void start() { controlThread.start(); } }
EtcherSketcher
import java.util.Enumeration; /** * A Drafter that draws in response to Point "events" generated by * one or more PointSubject objects * * @author Prof. David Bernstein, James Madison University * @version 1.0 */ public class EtcherSketcher extends Drafter implements PointObserver { /** * Default Constructor */ public EtcherSketcher() { super(); setPaperColor("black"); } /** * Descendants of the Drafter class must implement the * draw() method. In this case, all drawing is done in response to * Point "events" so this method is empty * * @param upperRight The coordinates of the upper right-hand corner */ public void draw(Point screenMax) { } /** * Handle a Point "event" * (required by PointObserver) * * @param subject The PointSubject that generated the Point * @param p The Point of interest */ public void handlePoint(PointSubject subject, Point r) { overlayPoint(r, "cyan"); } }
EtcherSketcherDriver
/** * An example that uses the EtcherSketcher to draw the Way icon * * @author Prof. David Bernstein, James Madison University * @version 1.0 */ public class EtcherSketcherDriver { /** * The entry point * * @param args The command line arguments */ public static void main(String[] args) { EtcherSketcher es; WayIconSubject subject; WayWindow window; es = new EtcherSketcher(); subject = new WayIconSubject(); subject.addPointObserver(es); window = new WayWindow(es); subject.start(); } }