1 / 28

Case Study A GUI Application using Design Patterns

Case Study A GUI Application using Design Patterns. Application overview MyShape class; Drawings; DrawingModel class Classes for Views and Controllers; Adapter & Template Method patterns Factory Method and Singleton DPs; MyShapeControllerFactory class Drag-&-Drop Controller

alma
Télécharger la présentation

Case Study A GUI Application using Design Patterns

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Case StudyA GUI Application using Design Patterns Application overview MyShape class; Drawings; DrawingModel class Classes for Views and Controllers; Adapter & Template Method patterns Factory Method and Singleton DPs; MyShapeControllerFactory class Drag-&-Drop Controller DrawingInternalFrame and associated classes; State design pattern The application class

  2. Application Overview • “Deitel Drawing” -- refer to Deitel, Deitel & Santry chapter 5 • A “painting” program featuring • colours, filled shapes, colour gradients • drag & drop moving of shapes and JPEG images between drawings • storage of drawings as XML documents • scaling to different sizes and aspect ratios • multiple drawing tools • choice of shape properties -- line, fill, gradient, … • MVC Architecture • Model is a collection of shape objects • Views create graphical presentations of these • Multiple controllers handle input for drawing shapes and dragging & dropping. MVT Architecture

  3. Application Overview • Java2D Graphics • drawing uses anti-aliasing • GradientPaint class draws shapes with multicoloured gradients • Transformation capabilities provide scaled views. • You can scale a drawing dynamically by resizing a ZoomDialog window • MVC architecture ensures each view is consistent: As user draws new shapes, each is immediately shown in each view. • Drag-and-Drop • Java drag-and-drop API allows the user to drag shapes between drawings • The user can also drag JPEG images from other applications. • Design Patterns • Uses Observer, Template Method, Adapter, Factory Method, Singleton, State MVT Architecture

  4. MyShape Class • Base class for a hierarchy of different classes representing the shapes which can be drawn. • Data members to store position and extent of shape, start and end posiiton and start and encolour (in case of gradient fill), fill attributes, stroke attributes • Get and set methods for these; a method to move by a given offset • Abstract Graphics2D draw method and boolean valued contains(point) method, implemented specifically in subclasses • A method getXML(Document) to generate an XML representation of the shape. Each subclass has an overriding method which calls super.getXML(…) then does subclass-specific generation. <<abstract>> MyShape MyLine MyRectangle MyOval MyText MyImage MVT Architecture

  5. MyShape Class and Drawings • A drawing is a collection of MyShape objects. • Note the use of the observer design patters as part of the MVC architecture. <<interface>> Observer <<abstract>> Observable JPanel 1 <<abstract>> MyShape * DrawingView DrawingModel ZoomDrawingView MVT Architecture

  6. Class DrawingModel • Data • A collection of shapes (objects of MyShape hierarchy) • Methods • to add a shape to / remove a shape from the collection • get / set / reset the shape collection • set “changed” flag & notify observers, as required of an Observable object MVT Architecture

  7. Class DrawingFileReaderWriter • Utility class with two public static methods • public static void writeFile(DrawingModel, String fileName) • Uses the getXML method of each shape in the DrawingModel’s collection to build up a composite XML element, and saves this to a file • public static Collection readFile(String fileName) • Reads file containing XML representation of a collection of shapes, parses it and obtains Collection of shapes. • Invoked by open and save methods of application internal frame (see later) • Various private static methods help with the parsing of the XML code • int getIntValueFromChildElement(Element parent, String childElementName) • float getFloatValueFromChildElement(...) • boolean getBooleanValueFromChildElement(...) • etc MVT Architecture

  8. XML Mechanics • XML Reference: DD&S Appendix A • An example ... <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE shapes SYSTEM "shapes.dtd"> <shapes> <shape type="MyLine"> <x1>163</x1><y1>165</y1><x2>51</x2><y2>36</y2> <startX>51</startX><startY>36</startY> <endX>163</endX><endY>165</endY> <useGradient>false</useGradient> <startColor red="0" green="0" blue="0"/> <endColor red="255" green="255" blue="255"/> <strokeSize>5.0</strokeSize><fill>false</fill> </shape> <shape type="MyOval"> <x1>135</x1><y1>46</y1><x2>213</x2><y2>124</y2> <startX>213</startX><startY>46</startY> <endX>135</endX><endY>124</endY> MVT Architecture

  9. XML Mechanics <useGradient>false</useGradient> <startColor red="255" green="0" blue="51"/> <endColor red="255" green="255" blue="255"/> <strokeSize>5.0</strokeSize><fill>false</fill> </shape> <shape type="MyText"> <x1>51</x1><y1>105</y1><x2>0</x2><y2>0</y2> <startX>0</startX><startY>0</startY> <endX>0</endX><endY>0</endY> <useGradient>false</useGradient> <startColor red="51" green="51" blue="255"/> <endColor red="255" green="255" blue="255"/> <strokeSize>1.0</strokeSize><fill>false</fill> <text>Hello</text><fontSize>18</fontSize><fontName>SansSerif</fontName> <underlined>false</underlined><bold>false</bold><italic>true</italic> </shape> </shapes> MVT Architecture

  10. Class DrawingView • Data • A reference to its DrawingModel • Methods • Constructor constructs a view for a given model • get / set the model • update(Observable, Object) required by Observer interface: just does a repaint() • drawShapes(Graphics2D) • iterates through the shapes in the model’s collection, calling each one’s draw method • paintComponent(Graphics g) • calls drawShapes(...) • g is cast to Graphics2D object reference • getPreferredSize() [320 X 240 pixels], getMinimumSize () [ditto], getMaximumSize () [ditto] • addNotify / removeNotify -- override Jpanel’s methods to include management of observer/observee association MVT Architecture

  11. Class ZoomDrawingView • Extends DrawingView • Additional Data • X, Y scale factors, java.awt.geom.AffineTransform object • Methods • Constructor of “zoomed” view for a given model and X-, Y-scale factors; • A ComponentListener is added which updates scale factors when window is resized • setScaleFactors(double X, doubleY) also sets the AffineTransform object to the new scale factors • drawShapes (Graphics2D) calls super.drawShapes after setting transform in Graphics2D object to this object’s AffineTransform object • getPreferredSize() overridden to take scale factors into account • Other methods as inherited from DrawingView. MVT Architecture

  12. Controllers <<abstract>> MyShapeController DrawingModel model Color priClr, secClr Class shapeClass …. DrawingModel JPanel get & set methods ... MyShape createNewShape() addShapeToModel(MyShape) removeShapeFromModel(…) startShape(int x, int y) endShape(int x, int y) modifyShape(int x, int y) TextInputPanel MyTextController MyLineController BoundedShapeController currentShape currentShape startShape(int x, int y) endShape(int x, int y) modifyShape(int x, int y) startShape(int x, int y) endShape(int x, int y) modifyShape(int x, int y) startShape(int x, int y) endShape(int x, int y) modifyShape(int x, int y) MVT Architecture

  13. MyShapeController • Abstract base class for 3 kinds of controller • one for bounded shapes, one for lines, one for text shapes. All take input primarily from mouse, but how input processed depends on type of shape being drawn. • Uses the Java Reflection Mechanism • Class Object has a getClass() method which returns an object of class Class. • Every class extends Object and so inherits this method. The method returns a Class object containing information about the runtime type (class) of the object. • The MyShapeController constructor takes parameters (DrawingModel, Class) and accordingly each controller object is constructed for a particular drawing model and shape. The Class parameter is the Class object for a particular MyShape subclass. • So a controller object knows what model it is controlling and also the type of shape it is intended for. The latter is stored in a data member shapeClass of type Class. • The reason for including this is that the controller can have a method MyShape createNewShape() which will create a new MyShape subclass object of the correct MyShape subclass -- ie the subclass corresponding to the value of shapeClass. • Class has a method newInstance() for doing this: MyShape shape = (MyShape)shapeClass.newInstance() ... return shape MVT Architecture

  14. MyShapeController • Data • the DrawingModel being controlled • primary and secondary colours for gradients • Class object for creating new MyShape subclass instances • common MyShape propoerties -- fillShape, useGradient (boolean), strokeSize (float) • dragmode (boolean) • references to assigned MouseListener and MouseMotionListener • Methods • Constructor constructs a controller for a given DrawingModel object and Class object denoting a particular MyShape subclass. • Also creates a MouseListener which will call startShape(…) on a mouse button press, endShape(…) on a mouse button release, and a MouseMotionListener which will call modfyShape(…) on a mouse drag. The event coordinates are supplied to the methods. • Get and set methods • MyShape createNewShape() as above • Methods to add a shape to / remove a shape from the model • abstract methods startShape(int x, int y), endShape(…), modfyShape(…). MVT Architecture

  15. Adapter Design Pattern • The MouseAdapter created in the constructor of MyShapeController adapts the MyShapeController (which also produces MouseEvents) to be able to handle MouseEvents -- it acquires MouseListener functionality. • Similarly, the MouseMotionListener is an example of the Adapter design pattern. <<interface>> MouseListener MyShapeController Java.awt.event.MouseAdapter MyShapeController anon MouseAdapter mousePressed(MouseEvent) mouseReleased(MouseEvent) MVT Architecture

  16. Controller Subclasses • BoundedShapeController • Implements startShape() by creating a new shape (MyOval, MyRectangle, …depending on construction of controller; using superclass’s createNewShape method) and adding it to the model. • Implements modifyShape() by removing the current shape from the model, modifying its position properties and adding it back to the model. • Implements endShape() simply with a call to modifyShape(). • MyLineController • Implements these methods similarly. Some differences in detail in modifyShape(). • MyTextController • startShape() construct a new MyTextShape and uses a TextInputPanel dialogue box to get text properties from the user. • modifyShape() and endShape() are empty. MVT Architecture

  17. Template Method Design Pattern <<abstract>> AbstractClass ... op1(); ... op2(); templateMethod( ) op1( ) op2( ) ConcreteClass ConcreteClass2 ... op1( ) op2( ) op1( ) op2( ) • MyShapeController uses this to ensure that all the subclasses follow the same 3-step algorithm for creating shapes -- specify start (click), specify extent (drag), specify end (release). • In the present case op1(), op2() are startShape(), modifyShape(), endShape(). All controller functionality is defined by the template methods are defined in the abstract base class MyShapeController; the subclasses merely provide alternative implementations of the abstract methods. • This desgn pattern ensures all controllers use a common structure. MVT Architecture

  18. MyShapeControllers and the Factory Method Design Pattern <<interface>> Product MyShapeControllerFactory newMyShapeController(DrawingModel model, String shapeClassName) : MyShapeController MyShapeController • The application is easily extensible by addition of new MyShape subclasses and new views. We would also have to add new MyShapeController subclasses. • To eliminate the need to change existing code when adding a new MyShapeController to the application, it make sense to use the Factory Method design pattern and provide class MyShapeControllerFactory which automatically constructs a controller subclass of appropriate type for each shape, at run time. • When new shape subclasses and controller subclasses are added, the implementation of MyShapeControllernewMyShapeController • (DrawingModel model, String shapeClassName) is the only exisitng code that needs to change. MVT Architecture

  19. MyShapeControllers and the Factory Method Design Pattern MyShapeControllernewMyShapeController(DrawingModel model, String shapeClassName) { try { Class shapeClass = Class.forName(MyShape.class.getPackage().getName() + “.” + shapeClassName); if (shapeClassName.equals(“MyLine”)) return new MyLineController(model, shapeClass); else if (shapeClassName.equals(“MyText”)) return new MyTextController(model, shapeClass); //if more controller subclasses, put more alternatives in here //.... else return new BoundedShapeController(model, shapeClass); } catch (ClassNotFoundException x) { ... } return null; } • Addition of new shape subclasses and/or new shape controller suclasses may necessitate changes to the if/else logic here. MVT Architecture

  20. Singleton (Creational) Design Pattern Used when we want a class to have exactly one instance. The class itself keeps track of its sole instance. The class ensures no other instance can be created -- eg with just one constructor which is protected (see below) and provides a way to access the unique instance. Singleton static uniqueInstance otherData static getInstance() getOtherData() othewrOperation() protected Singleton() { } if (uniqueInstance == null) uniqueInstance = new Singleton() return uniqueInstance() • This is indeed the case with MyShapeControllerFactory. • Accordingly the factory class’s constructor is protected and the getInstance() method has, essentially the logic above. MVT Architecture

  21. Class DragAndDropController • Two kinds of dragging and dropping • drag & drop MyShapes between drawings in the MDI, or with drawings • drag & drop JPEG images from file manager • Interface DragGestureListener specifies method dragGestureRecognized(DragGestureEvent). In this implementation, • it scans backwards through the list of shapes and finds the one containing the point from which the drag originated. • It then constructs a TransferableShape object from the shape being dragged and initiates dragging of this with a call to event.startDrag(). <<interface>> DragSourceListener <<interface>> Transferable <<interface>> DropTargetListener <<interface>> DragGestureListener DragAndDropController TransferrableShape DrawingModel MVT Architecture

  22. Class DragAndDropController • Interface DropTargetListener requires a method drop(DropTargetDropEvent). • This implementation gets the object to drop and the location from the event object, and processes the drop with a call to private helper method dropImages(…) in case of JPEG(s) being dragged/dropped, and with a call to to private helper method dropShape(…) in case of a MyShape object. • Both helper methods take as parameters a drop Location and TransferableShape object wrapping the shape object being transferred. • Both helper methods unpack the shape from the TransferrableShape object and add it to the target DrawingModel. • Interface DragSourceListener requires a method dragDropEnd(DragSourceDropEvent). • This implementation checks if the drag-&-drop was successful and in that case (and if it was a move rather than a copy), removes the shape from the source DrawingModel. • Interfaces DragSourceListener and DropTargetListener both require implementations of methods dragEnter(...), dragExit(…), dragOver(…), dropActionChanged(…). • Empty implmentations are used here. • The parameters are DragSourceDragEvents or DragSourceEvents in the case of the DragSourceListener, and DropTargetDragEvents or DropTargetDragEvents in case of the DropTargetListener. • The class TransferableShape wraps the shape object to be transferred and implements a number of methods requred by the Transferrable interface. • Refer to the java documentation for this interface.. MVT Architecture

  23. DrawingInternalFrame class Observer JInternalFrame DrawingModel Action ZoomDrawingView DrawingView 6 DrawingInternalFrame MyShapeController (subclasses) Drawing ToolBar MyShapeControllerFactory JFileChooser Icon (etc) DragAndDropController Drawing FileFilter Zoom Dialog GradientIcon JDialog (for Gradient toolbar button) AbstractDrawingAction (see below) FileFilter MVT Architecture

  24. DrawingInternalFrame class • Remember this application has a multiple document interface. This subclass of JInternalFrame proves the graphical window for one of (potentially) several drawings which may be open at any one time. • 700 lines of code devoted to setting up and managing the user interface for a particular drawing • Data • (current) DrawingModel, DrawingView, MyShapeControllerController • DragAndDropController • File management data -- JFileChooser, (String) file name, path; (boolean) saved • DrawingToolBar, ZoomDialog • Action objects (see below) for save, saveAs, zoom, move, fill, gradient • Methods • Constructor • Get / set methods • (Method setMyShapeController(…) also registers myShapeController’s MouseListener & MouseMotionListener as listeners for the DrawingInternalFrame.) • close() • if (!saved) saveDrawing() MVT Architecture

  25. DrawingInternalFrame class • Methods (ctd) • openDrawing() • saveDrawing() • saveDrawingAs() • showZoomDialog() • Inner class DrawingToolBar • Buttons for initiating setting shape type, stroke size, fill, gradient, colours • Action objects (data members of DrawingInternalFrame; see above & below) for save, saveAs, zoom, move, fill, gradient are constructed as new AbstractDrawingAction objects • Action objects “connected” to Buttons • Action objects and Buttons added to tool bar • Action objects: <<interface>> javax.swing.Action <<abstract>> javax.swing.AbstractAction <<abstract>> AbstractDrawingAction MVT Architecture

  26. DrawingInternalFrame -- Action objects • The Action interface and AbstractAction class are provided by swing as a convenient way to manage multiple actions to be taken in response to ActionEvents. • The ActionEvent class provides default implementations for the JFC Action interface. Standard behaviours like the get and set methods for Action object properties (icon, text, and enabled) are defined here. To use it, we need just to subclass this abstract class and define the actionPerformed() method. • The AbstractDrawingAction class • sets Action properties -- name, icon, short description, mnemonic key • actionPerformed method is still abstract. • The DrawingToolBar contructor constructs the Action objects for DrawingInternalFrame as objects of anonymous subclasses of AbstractDrawingAction, with actionPerformed(...) methods defined in-line. • Now, an ActionEvent from the tool bar will call the appropriate actionPerformed(...) method via the Action object data members for save, saveAs, zoom, move, fill, gradient. MVT Architecture

  27. State (Behavioural) Design Pattern in DrawingInternalFrame state Context <<abstract>>State Request1(...) Request2(...) handle1(...) handle2(...) state.handle1() ConcreteStateA ConcreteStateB handle1(...) handle2(...) handle1(...) handle2(...) • Used when we want an object to alter its behaviour according to the internal state it is in. • The object delegates state-specific requests to State object. • Subclasses implement state-specific behaviour • In this case, the “Context” class is DrawingInternalFrame and “State” class the MyShapeController base class. • Changing the current shape to draw changes the MyShapeController subclasses and hence the specific controller behaviour • A convenient architecture when we might want to extend the application by adding new shape and shape controller types. MVT Architecture

  28. DeitelDrawing JFrame JMenuBar JMenu DeitelDrawing JMenuItem SplashScreen JDesktopPane Action • A series of Action objects are constructed in the same way as in DrawingInternalFrame, to handle commands from the menus. • Opening or Creating a new Drawing constructs a new DrawingInternalFrame and attches it to the JDesktopPane: thereafter it beaves as a self-contained entity. MVT Architecture

More Related