CIS 3760 – Winter 2021 Take-Home Final Exam – Part II Instructions
Released: April 15, 2021 – 9:00am (Guelph local time, EDT) Due Date: April 19, 2021 – 5:00pm (Guelph local time, EDT) Instructor: Prof. S. Scott
Introduction and Rules:
The Final Exam ‐ Part II is an open book, take‐home exam. You are allowed the following resources:
Any informational resources, including: o CIS 3760 lecture notes
o Course Materials posted on CIS 3760 CourseLink site (Readings, Videos, etc.) o Course textbooks (Shvets; Kniberg)
o Your personal course notes.
o The internet
All content in your answers that are not your own ideas, thoughts, examples, etc. MUST be cited You are NOT allowed to use:
No collaboration or communication with ANYONE about this Take‐Home Final Exam ‐ this is considered cheating
No posting of Exam content ‐ questions and/or answers ANYWHERE accessible by others (publicly, privately, etc.) ‐ this is considered cheating
AS A TAKE‐HOME EXAM, STUDENTS WILL BE COMPLETING THE FINAL EXAM AT
DIFFERENT TIMES.
NO COMMUNICATIONS OR INFORMATION SHARING ABOUT THIS EXAM IS
ALLOWED UNTIL AFTER 5PM ON APRIL 19TH.
TO DO SO VIOLATES THE UNIVERSITY OF GUELPH’S ACADEMIC MISCONDUCT
POLICIES:
https://www.uoguelph.ca/registrar/calendars/undergraduate/2018‐2019/c08/c08‐amisconductoffen.shtml
Please read questions carefully before answering. NO QUESTIONS related to the exam content will be answered during this exam. If you are unsure about a question, explicitly state your assumptions in your solution.
Good luck!
University of Guelph ‐ CIS 3760 Take‐Home Final Exam – Part II (W21) 1/9
Instructions for Completing and Submitting Your Answers
Create two answer files:
o Modeling document (for Q1 only): This should be submitted in PDF format.
o Written / essay answer document (for all other Q’s): This should be submitted in a format readable by the Turnitin® system. Most popular formats are accepted, but please check the following information page from Turnitin® to be sure about your file format. Note, Apple Pages files are NOT supported and some PDF files (i.e. those that save the content as an image) are not readable:
https://help.turnitin.com/feedback‐studio/d2l/student/submitting‐a‐paper/file‐types‐ and‐size.htm
Please use the following naming convention for your submitted file:
o Modeling document: lastname_firstname_cis3760_final_W21_modeling.PDF (must be in PDF
format)
o Written answer document: lastname_firstname_cis3760_final_W21_written.XXX (whatever file format you use)
Label each question being answered clearly. (e.g. Q1, Q3a, …)
Write answers in clear, organized, concise paragraphs. Use bullet points if appropriate for the answer.
Submit the above files to the appropriate Final Exam – Part II Dropbox (i.e., “Part II – Modeling” and “Part II – Written”) on CourseLink by the due date (NO LATE EXAMS WILL BE ACCEPTED, SO BE PREPARED – SUBMIT EARLY!)
o You can submit as many times as you like. Only the newest file will be marked.
Contact Prof. Scott as soon as possible if you experience technical difficulties (e.g. lose internet or power) while trying to complete or submit your exam. You are expected to take all reasonable steps to preserve the integrity of the exam. For example, take a screenshot, or a picture with your mobile phone, of the time‐stamped document properties showing last modified date clearly within the exam time window.
Answers MUST Properly Cite Sources
As we have discussed in class, it is important to answer questions with your own knowledge, explanations, and example to clearly demonstrate your strong understanding of the concepts and how those concepts connect together. Simply echoing back content verbatim or paraphrased directly from course materials or external sources without providing further explanation, relevant examples, or connection to other content will earn you little to no points on the exam.
Also, you must properly cite any information source you use in your answer that is not your own idea, thought, or example. If in doubt, cite it. A quick video from UofG that overviews how to check your work for plagiarism is provided below. The main messages are, 1) when in doubt, cite your source and 2) use enough of your own “voice” (your own words, ideas, examples, etc.) in addition to the sources to clearly demonstrate your own understanding of the material:
https://learningcommons.lib.uoguelph.ca/item/4‐ways‐check‐your‐paper‐plagiarism
University of Guelph ‐ CIS 3760 Take‐Home Final Exam – Part II (W21) 2/9
Your written answers will be submitted to the Turnitin® tool (integrated directly into the Final Exam Dropbox). The Turnitin® tool (https://support.opened.uoguelph.ca/students/courselink/tools/content/notifications‐ hsw2e‐psl9k, https://help.turnitin.com/Home.htm, && https://help.turnitin.com/feedback‐studio/d2l/d2l‐ home.htm) provides a “similarity” score for your submitted work, based on a comparison against its extensive content database (websites, student submissions, including your own classmates ‐ after all students have submitted). This score provides a tool for the instructional team to investigate potential issues with content in a student’s answer that is overly similar to content found elsewhere. The instructional team will use our knowledge and discretion when interpreting any flagged content (as we always do). The main take‐away is that if you do your own work, there will not be a problem.
Some examples of how to cite a source are provided with the Final Exam – Part II Instructions on CourseLink.
University of Guelph ‐ CIS 3760 Take‐Home Final Exam – Part II (W21) 3/9
Questions 1 and 2 are based on the ShapeDrawApp Java program and associated shapeDraw Java package
code provided in Appendix A of this document.
QUESTION 1 SHOULD BE INCLUDED IN THE “MODELING” DOCUMENT AND SUBMITTED TO THE PART II –
MODELING DROPBOX.
QUESTION 1. MAPPING CODE TO MODELS [5 marks]
Draw a UML class diagram that models the static structure of the shapeDraw Java package.
Include all shapeDraw package classes, but only fully specify the Square and Rectangle classes. For all
other shapeDraw classes, include their class names only.
Include all associations between participating classes. Be as specific as possible for included
associations
o E.g., specify aggregation, composition, or inheritance relationships where appropriate.
o Include multiplicity on associations
o For the fully specified Square class, note the visibility of attributes and operations (methods)
The UML class diagram must be created without the use of any external aids, including automated tools, collaboration, etc.
The diagram must be created by hand, on paper.
‐ Draw your UML diagram on paper (please be as neat as possible; use a ruler/straight edge if you can)
‐ Make sure your sign and date your name somewhere clearly visible on the diagram
‐ Take a digital photo of your completed diagram (e.g. using your mobile phone camera)
‐ Import your digital photo to a document that you can save as a PDF file (or convert your diagram to
a PDF file). Make sure you use the “Modeling” file naming convention described above.
‐ Upload your PDF file to the “Final Exam ‐ Part II ‐ Modeling”
o You can also upload your original photo as backup, but this should not replace your PDF submission.
Make sure your diagram is clearly labeled to demonstrate your understanding of the structural relationship between the entities.
Make sure the submitted picture of your diagram clearly shows your written signature and the date.
All REMAINING QUESTIONS SHOULD BE INCLUDED IN THE “WRITTEN ANSWERS” DOCUMENT AND
SUBMITTED TO THE PART II – WRITTEN ANSWERS DROPBOX.
University of Guelph ‐ CIS 3760 Take‐Home Final Exam – Part II (W21) 4/9
QUESTION 2. SOFTWARE REUSE [15 marks total]
Q2a. [10 marks] Identifying Software Reuse in Code/Models
The shapeDraw java package modeled in Q1 utilizes many different software reuse concepts that we have discussed in this course. Identify and discuss one (1) instance of each of the following objected‐oriented reuse concepts contained in this code:
Implementation inheritance
Specification inheritance
Composition (you cannot use the Square‐Rectangle Composition relationship discussed in Q2b)
Aggregation
A design pattern we’ve covered in this course (Adapter, Bridge, Observer, Factory Method, Abstract
Factory) ‐ which one and where is it in the code
Using your own words, explain any reuse concepts appearing in the code, describe where they appear in the
code, and discuss the benefit of using this type of reuse concept in the software engineering process. (Max word count for answer: 500)
Q2b. [5 marks] Composition vs. Inheritance
The Square class in the shapeDraw java package implements an important object‐oriented reuse concept we have seen used in many design patterns, called composition (or delegation), whereby an existing object is encapsulated (or “wrapped”) and incoming calls are passed along to the encapsulated object. In the Square class, the Rectangle functionality is reused by encapsulating a Rectangle object, “rect”. However, as you know, code can be designed many ways. An alternative design is to define Square class as a specialized type of Rectangle (i.e. “Square is a Rectangle”) by using inheritance (i.e. “public class Square extends Rectangle {…}”).
In your own words, describe the benefits that composition can provide over inheritance in object‐oriented design in general. Example why composition is a better choice for reusing the existing functionality of Rectangle to implement Square than inheritance would be in the design context of the shapeDraw package. Be as specific as possible.
(Max word count for answer: 250)
University of Guelph ‐ CIS 3760 Take‐Home Final Exam – Part II (W21) 5/9
Question 3 is based on the ilovedragons Java package code provided in Appendix B of this document.
QUESTION 3. DESIGN PATTERNS [10 marks total]
Q3a. [3 marks total; 1⁄2 mark each] Code to Model Mapping
The ilovedragons Java package implements the Abstract Factory design pattern (shown in Figure 3 below). The general concept behind the code is that each main dragon character from the “How to Train Your Dragons” Movie/TV franchise has unique characteristics, but they all have skin/scale texture, fire breathing capabilities, and other properties that would need to be rendered during animation of these characters. For example, the dragons Toothless (Figure 2, left) and Stormfly (Figure 2, right) have different skin textures, both in colour and smoothness, and also different fire breathing capabilities.
Figure 1. Toothless (left) and Stormfly (right).
Figure 2. Abstract Factory Design Pattern, represented in UML Class Diagram form.
© Kitsunes97 @ DreamworksWiki
© Frie‐ice @ DreamworksWiki
University of Guelph ‐ CIS 3760 Take‐Home Final Exam – Part II (W21) 6/9
Each black call‐out bubble, B to I, in Figure 3, represents a class, interface, or method in the ilovedragon Java package that plays a corresponding role in the Abstract Factory design pattern indicated by the call‐out. For instance, “A” corresponds to the “App class” in the ilovedragons Java package code.
Some of the entities are already identified below. In your “Written answer” document, complete the following by naming the missing entities. Clearly label your answers by the corresponding call‐out letters. Also, specify whether the entity is a class, interface, or method.
B: DragonFactory ‐ interface C:
D:
E:
F:
G:
H: ToothlessFirebreath ‐ class I:
Q3b. [7 marks total] Extending the ilovedragons Java package
A benefit of the Abstract Factory design pattern is its ability to support extensions to an existing system. There are many other dragons in the How to Train Your Dragon world. An interesting dragon is Hookfang (Figure 4) who can light his whole body on fire as a defence mechanism. Also, there are many other types of dragon characteristics, beyond skin texture and fire breathing capabilities, that we would want to render for each of our dragons to complete their look and behaviour. For instance, each dragon has different flight dynamics due to its size and shape.
Following the existing implementation of the Abstract Factory design pattern, describe in words what classes, interfaces, methods, etc. you would need to add to the existing code / system design to realize the following program extensions:
Adding the dragon type “Hookfang”, and
Adding the Flightdynamics dragon characteristic.
If you’d like to add a supplemental diagram to accompany your answer, please hand draw, sign, date, and take a picture of your diagram, and then import it into the “Written answer” document along with your written description.
(Max word count for answer: 300)
© Erebus Elysium @ DreamworksWiki
Figure 3. Hookfang
University of Guelph ‐ CIS 3760 Take‐Home Final Exam – Part II (W21)
7/9
QUESTION 4. SOFTWARE QUALITY AND DEFECT HANDLING [10 marks total]
Figure 4. Relative Cost of Fixing a Defect (note, UAT = User Acceptance Testing).
Figure 4 shows a graph we’ve discussed several times in this course. It depicts the relative cost of fixing a defect, depending in which software development phase the defect is found. For instance, if the defect is found during the requirements phase, it may cost $1 to fix. If the defect is found, instead, in the design phase it may cost $5 to fix. Note, in this context the word “defect” refers broadly to any mistake, error, incorrect assumption, etc., the software team makes anywhere during the software engineering (SE) process that contributes to the final product not working effectively for the user.
In this course, we have discussed in detail many of the defect handling approaches shown in Figure 5 (see next page). Different approaches have more or less potential to help a software company find and correct defects earlier in the SE process to help reduce the exponential costs shown in Figure 4.
Q4a. [3 marks]
The data shown in Figure 4 is based on waterfall‐style projects. Discuss how the choice of SE methodology, specifically the choice of waterfall vs. agile/Scrum, impacts a software company/team’s ability to reduce the exponential costs shown in Figure 4. Be as specific as possible about how methodology impacts the software team’s ability to find and correct defects as early as possible in a project.
Q4b. [7 marks]
Assume a waterfall‐based project. Select one static analysis defect handling approach and one dynamic analysis (i.e. testing) defect handling approach. In your own words, briefly describe each approach and discuss its potential to reduce the exponential costs shown in Figure 4. Consider the following issues:
How effective is each approach at finding and correcting potential defects as early as possible in the project? Be specific about which stage(s) each approach can be applied.
Which selected approach is likely have a larger impact on reducing costs and why? (Max word count for both parts: 600)
(Figure 5 on next page)
University of Guelph ‐ CIS 3760 Take‐Home Final Exam – Part II (W21) 8/9
Figure 5. Taxonomy of Defect Handling Approaches.
University of Guelph ‐ CIS 3760 Take‐Home Final Exam – Part II (W21) 9/9
CIS 3760 – Final Exam (W21)
Appendix A: ShapeDrawApp & shapeDraw package Code Listing
10 pages (including this one)
Included java classes/interfaces: ShapeDrawApp.java (test application) shapeDraw package classes: Line.java
Node.java NodeChangeListener.java Shape.java
Circle.java Rectangle.java Square.java Triangle.java
1 / 10
/***********************************************************************************/ // ShapeDrawApp.java
// This is a simple application that tests the shapeDraw java package defined below. // This application opens a simple window containing three user interface buttons
// along the top of the window, labeled Draw Square, Draw Circle, and Draw Triangle. // When the user selects a button, the shape draw on the window canvas changes to match // the selected shape type. When the window launches, a square is drawn by default. /************************************************************************************/
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import javax.swing.JPanel;
import shapeDraw.*; import javax.swing.JFrame;
import javax.swing.JButton;
public class ShapeDrawApp extends JPanel implements ActionListener{
private JButton squareButton; private JButton circleButton; private JButton triangleButton; private Shape currentShape;
// Constructor: creates the “Draw Shape” buttons and adds them
// to this JFrame container. By default they are centred at the top // of the container. It sets the default shape to a square
// and gives it an initial position and size.
public ShapeDrawTest() {
}
}
// set initial shape to square, with initial position and size this.currentShape = new Square(300, 300, 300); //centreX, centreY, size
// create buttons
this.squareButton = new JButton(“Draw Square”); this.circleButton = new JButton(“Draw Circle”); this.triangleButton = new JButton(“Draw Triangle”);
//set up event callbacks for these buttons
squareButton.addActionListener(this); circleButton.addActionListener(this); triangleButton.addActionListener(this);
//add to frame
this.add(this.squareButton); this.add(this.circleButton); this.add(this.triangleButton);
// Draw the shape to the screen
public void paintComponent(Graphics g) { super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
currentShape.draw(g2d);
// class cont’d on next page
2 / 10
// Main application method. Creates main application window for user interface // Adds the “ShapeDrawApp” JFrame container to the main window
public static void main(String[] input) {
JFrame frame = new JFrame(“Shape Draw”); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new ShapeDrawTest());
frame.setSize(600, 600); frame.setLocationRelativeTo(null); frame.setVisible(true);
}
@Override
// Method called when any of the UI buttons are pressed by the user.
// Used to set the current shape, based on the button pressed, and then once // the shape is set, repaints the screen so the shape visualization is updated. public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source instanceof JButton) {
if (((JButton) source).getText().equalsIgnoreCase(“Draw Square”)) { this.currentShape = new Square(this.getWidth()/2, this.getHeight()/2,
this.getWidth()/2);
} else if (((JButton) source).getText().equalsIgnoreCase(“Draw Circle”)) {
this.currentShape = new Circle(this.getWidth()/2, this.getHeight()/2, this.getWidth()/4);
} else if (((JButton) source).getText().equalsIgnoreCase(“Draw Triangle”)) { this.currentShape = new Triangle(this.getWidth()/2, this.getHeight()/2,
} }
this.repaint(); } // End of ShapeDrawApp class
}
3 / 10
this.getWidth()/2);
/********************************************************************/ // shapeDraw package classes
// The basic functioning of the shapes in this package is that each
// shape is defined by a list of nodes (i.e. corner points, or the whole // circumference of a circle) and lines connecting the corners. Nodes // are defined separately so they can be drawn as thicker “dots”
// in the interface while lines remain thin. Lines are defined
// as a start node and end node. When either node changes position, // for instance, because a shape was resized or moved, the line is
// notified of the change and it updates itself accordingly. /********************************************************************/
/********************************************************************/ /* Line.java */ /********************************************************************/
package shapeDraw;
import java.awt.Graphics2D; import java.util.EventObject;
//Line connects two nodes with an undirected line
public class Line implements NodeChangeListener { private Node startNode;
private Node endNode;
// Constructor: sets the start and end coordinates (startPoint, endPoint) // of the starting and ending nodes, sets the ids of the starting and
// ending nodes located at the start and end of this line. It then
// registers itself with the NodeChangeListener to learn about
// any changes about the start or end nodes.
public Line(Node start, Node end) { this.startNode = start;
}
this.endNode = end;
// listen for node change events
start.addNodeChangeListener(this); end.addNodeChangeListener(this);
// draw to screen
public void draw(Graphics2D g2d) {
g2d.drawLine(this.startNode.getCenterX(), this.startNode.getCenterY(),
}
//handle node location update
this.endNode.getCenterX(), this.endNode.getCenterY());
public void handleNodeChangeEvent(EventObject e) {
if (e != null && e.getSource() instanceof Node) {
Node changed = ((Node) e.getSource());
// determine which node was changed and update accordingly
if (changed.getId() == this.startNode.getId()) { this.startNode = (Node) e.getSource();
} else if (changed.getId() == this.endNode.getId()) { this.endNode = (Node) e.getSource();
} }
}
} // End of Line class
4 / 10
/********************************************************************/ /* Node.java */ /********************************************************************/ package shapeDraw;
import java.awt.Graphics2D; import java.awt.Point; import java.util.ArrayList; import java.util.List; import java.util.EventObject;
// Node represents one node (dot) on the canvas
public class Node {
private int id; //id of this node
private Point location; //location of this node
private int size = 10; //size of a node
private List
//Constructor: sets node id, x location, and y location
public Node(int id, int x, int y){ //initialize all variables
this.id = id;
this.location = new Point(x, y);
this.listeners = new ArrayList
}
public int getId() { return this.id; }
public int getX() { return location.x; }
public int getY() { return location.y; }
public int getCenterX() { return location.x + this.size/2; } public int getCenterY() { return location.y + this.size/2; }
// update the location of this node and let listeners know that location is updated
public void updateNodeLocation(int x, int y) { this.location = new Point(x, y); this.fireNodeChangeEvent();
}
public void draw(Graphics2D g2){
//draw circle with Node.size using (x,y) as the top left corner //fill the whole circle from degree 0 to 360 g2.fillArc(this.getX(), this.getY(), this.size, this.size, 0, 360);
}
//add a listener for node change event
public void addNodeChangeListener(NodeChangeListener listener){ this.listeners.add(listener);
}
//remove a listener
public void removeNodeChangeListener(NodeChangeListener listener){ this.listeners.remove(listener);
}
//notify listeners of changes
private void fireNodeChangeEvent(){
EventObject event = new EventObject(this);
for (NodeChangeListener i : this.listeners) { i.handleNodeChangeEvent(event);
} }
} // End of Node class
5 / 10
/********************************************************************/ /* NodeChangeListener.java */ /********************************************************************/ package shapeDraw;
import java.util.EventObject;
// a listener that observes the changes in a node
interface NodeChangeListener{
// handle changes in a node
void handleNodeChangeEvent(EventObject e);
} // End of NodeChangeListener interface
/********************************************************************/ /* Shape.java */ /********************************************************************/ package shapeDraw;
import java.awt.Graphics2D; import java.util.ArrayList; import java.util.List;
public class Shape {
protected List
protected List
// Constructor: initialize the node and line lists
public Shape() {
this.nodeList = new ArrayList
}
// Update the lineList based on the current list of nodes
protected void updateLineList() {
// update associated Lines attached to these nodes this.lineList.clear();
for (Node node : this.nodeList) {
if (node.getId() != nodeList.size()){
this.lineList.add(new Line(node, this.nodeList.get(node.getId())));
} else { // Last node in list, needs to wrap to first node this.lineList.add(new Line(node, this.nodeList.get(0)));
} }
// draw Shape to screen, by drawing all nodes first, then all lines
public void draw(Graphics2D g2d) { for(Node n: this.nodeList){
n.draw(g2d);
for(Line line : this.lineList){
}
}
line.draw(g2d);
} // End of Shape class
} }
6 / 10
/********************************************************************/ /* Circle.java */ /********************************************************************/ package shapeDraw;
public class Circle extends Shape { private int centreX;
private int centreY; private int radius;
// Constructor: sets the centre position of circle to (centreX, centreY) and sets its // radius length. It then generates the circle coordinates.
public Circle (int centreX, int centreY, int radius) {
}
super();
this.centreX = centreX; this.centreY = centreY; this.radius = radius;
createCircle(); // generate the circle using the centre position and radius
// update the position and/or radius length of the circle
public void updateShape(int centreX, int centreY, int radius) { this.centreX = centreX;
this.centreY = centreY;
this.radius = radius;
createCircle(); // generate the circle using the centre position and radius
}
// Creates a circle using the midpoint algorithm, centred at // (centreX, centreY) and using “radius” as its circle radius. private void createCircle(){
int x0 = this.centreX; // use temp var for brevity of midpoint algorithm code below int y0 = this.centreY; // use temp var for brevity of midpoint algorithm code below int x = this.radius; // set x to the radius
int y = 0;
int err = 0;
int nodeCounter = 1; while (x >= y) {
this.nodeList.add(new Node(nodeCounter++, x0 + x, y0 + y)); this.nodeList.add(new Node(nodeCounter++, x0 + y, y0 + x)); this.nodeList.add(new Node(nodeCounter++, x0 ‐ y, y0 + x)); this.nodeList.add(new Node(nodeCounter++, x0 ‐ x, y0 + y)); this.nodeList.add(new Node(nodeCounter++, x0 ‐ x, y0 ‐ y)); this.nodeList.add(new Node(nodeCounter++, x0 ‐ y, y0 ‐ x)); this.nodeList.add(new Node(nodeCounter++, x0 + y, y0 ‐ x)); this.nodeList.add(new Node(nodeCounter++, x0 + x, y0 ‐ y));
if (err <= 0) { y += 1;
err += 2*y + 1; } else { // (err > 0)
x ‐= 1;
err ‐= 2*x + 1;
}
}
// clear the lineList; node points will completely fill circle circumference
this.lineList.clear(); }
} // End of Circle class
7 / 10
/********************************************************************/ /* Rectangle.java */ /********************************************************************/ package shapeDraw;
public class Rectangle extends Shape { private int centreX;
private int centreY; private int height; private int width;
// Constructor: sets the centre position of rectangle to (centreX, centreY) and sets its // height and width. It then generates the rectangle coordinates.
public Rectangle (int centreX, int centreY, int height, int width) {
}
}
super();
this.centreX = centreX; this.centreY = centreY; this.height= height; this.width= width;
createRectangle();
// Updates the centre position of rectangle to (centreX, centreY) and its // height and width. It then generates the rectangle coordinates.
public void updateShape(int centreX, int centreY, int height, int width) {
this.centreX = centreX; this.centreY = centreY; this.height= height; this.width = width;
createRectangle();
// Generates the four corner coordinates based on the centreX, centreY position and its // height and width.
private void createRectangle(){
this.nodeList.clear();
Node node1 = new Node(1, this.centreX ‐ this.width/2, this.centreY ‐ this.height/2); Node node2 = new Node(2, this.centreX ‐ this.width/2, this.centreY + this.height/2); Node node3 = new Node(3, this.centreX + this.width/2, this.centreY + this.height/2); Node node4 = new Node(4, this.centreX + this.width/2, this.centreY ‐ this.height/2);
this.nodeList.add(node1); this.nodeList.add(node2); this.nodeList.add(node3); this.nodeList.add(node4);
this.updateLineList(); } // End of Rectangle class
}
8 / 10
/********************************************************************/ /* Square.java */ /********************************************************************/ package shapeDraw;
import java.awt.Graphics2D;
public class Square extends Shape {
private Rectangle rect; // Reuse a Rectangle object to represent this square
// constructor: set the centre X,Y coordinates, and the size (width/height) // of the square
public Square (int centreX, int centreY, int size) {
}
super();
// create a rectangle with equal height/width
this.rect = new Rectangle(centreX, centreY, size, size);
// update the position and/or size of the square
public void updateShape(int centreX, int centreY, int size) { this.rect.updateShape(centreX, centreY, size, size);
}
@Override
// wrap the draw method of the rectangle, so it draws correctly (the nodeList and // lineList for the rect object are not visible the this object, so the super.draw() // method will not work correctly.
public void draw(Graphics2D g2d) {
this.rect.draw(g2d); } // End of Square class
}
9 / 10
/********************************************************************/ /* Triangle.java */ /********************************************************************/ package shapeDraw;
import java.lang.Math;
public class Triangle extends Shape { private int centreX;
private int centreY; private int size;
// Constructor: defines an equilateral triangle, centred at (centreX, centreY) // and with side length of “size”.
public Triangle (int centreX, int centreY, int size) {
}
super();
this.centreX = centreX; this.centreY = centreY; this.size = size;
this.createTriangle();
// update the position and/or size of the rectangl
public void updateShape(int centreX, int centreY, int size) { this.centreX = centreX;
this.centreY = centreY; this.size = size;
this.createTriangle();
// Generates an equilateral triangle, centred at (centreX, centreY) and side length “size”.
}
private void createTriangle(){
this.nodeList.clear();
Node node1 = new Node(1, this.centreX,
(int)(this.centreY ‐ this.size*Math.sqrt(3)/3)); Node node2 = new Node(2, (int)(this.centreX ‐ this.size/2),
(int)(this.centreY + this.size*Math.sqrt(3)/6)); Node node3 = new Node(3, (int)(this.centreX + this.size/2),
(int)(this.centreY + this.size*Math.sqrt(3)/6));
this.nodeList.add(node1); this.nodeList.add(node2); this.nodeList.add(node3);
for (Node node : this.nodeList) {
if (node.getId() != nodeList.size()){
this.lineList.add(new Line(node, this.nodeList.get(node.getId()))); } else { // Last node in list, needs to wrap to first node
} }
this.updateLineList(); } // End of Triangle class
}
this.lineList.add(new Line(node, this.nodeList.get(0)));
10 / 10
CIS 3760 – Final Exam (W21)
Appendix B: DragonApp & ilovedragons package Code Listing
5 pages (including this one)
Included java classes/interfaces: DragonApp.java (test application) ilovedragons package classes: DragonFactory.java StormflyDragonFactory.java ToothlessDragonFactory.java Texture.java ToothlessTexture.java StormflyTexture.java Firebreath.java Toothless Firebreath.java StormflyFirebreath.java
1/5
/********************************************************************/ /* DragonApp.java */ /********************************************************************/
package ilovedragons;
import ilovedragons.DragonApp.FactoryMaker.DragonType;
public class DragonApp {
/**
* The factory of dragon factories.
*/
public static class FactoryMaker {
/**
* Enumeration for the different types of Dragons.
*/
public enum DragonType { TOOTHLESS, STORMFLY, HOOKFANG }
/**
* The factory method to create DragonFactory concrete objects.
*/
public static DragonFactory makeFactory(DragonType type) { switch (type) {
case TOOTHLESS:
return new ToothlessDragonFactory();
case STORMFLY:
return new StormflyDragonFactory();
default:
throw new IllegalArgumentException(“DragonType not supported.”);
} }
}
/**
* Program entry point.
*/
public static void main(String[] args) {
DragonFactory dragonfactory;
Texture texture;
Firebreath firebreath;
// Create the Dragon “Toothless”
System.out.println(“The Dragon \”Toothless\”.”);
dragonfactory = FactoryMaker.makeFactory(DragonType.TOOTHLESS); texture = dragonfactory.createTexture();
firebreath = dragonfactory.createFirebreath(); System.out.println(texture.getDescription()); System.out.println(firebreath.getDescription() + “\n”);
// Create the Dragon “Stormfly”
System.out.println(“The Dragon \”Stormfly\”.”);
dragonfactory = FactoryMaker.makeFactory(DragonType.STORMFLY); texture = dragonfactory.createTexture();
firebreath = dragonfactory.createFirebreath(); System.out.println(texture.getDescription()); System.out.println(firebreath.getDescription());
} }
2/5
/********************************************************************/ /* DragonFactory.java */ /********************************************************************/
package ilovedragons;
/** *
* DragonFactory factory interface.
*
*/
public interface DragonFactory { Firebreath createFirebreath(); Texture createTexture();
}
/********************************************************************/
/* StormflyDragonFactory.java */ /********************************************************************/ package ilovedragons;
/**
* StormflyDragonFactory concrete factory.
*/
public class StormflyDragonFactory implements DragonFactory {
public Firebreath createFirebreath() { return new StormflyFirebreath();
}
public Texture createTexture() { return new StormflyTexture();
} }
/*******************************************************************/ /* ToothlessDragonFactory.java */ /********************************************************************/ package ilovedragons;
/**
* ToothlessDragonFactory concrete factory.
*/
public class ToothlessDragonFactory implements DragonFactory {
public Firebreath createFirebreath() { return new ToothlessFirebreath();
}
public Texture createTexture() { return new ToothlessTexture();
} }
3/5
/*******************************************************************/ /* Texture.java */ /********************************************************************/ package ilovedragons;
/** *
* Texture interface
*
*/
public interface Texture { String getDescription();
}
/*******************************************************************/ /* ToothlessTexture.java */ /********************************************************************/ package ilovedragons;
/** *
* ToothlessTexture
*
*/
public class ToothlessTexture implements Texture {
static final String DESCRIPTION = “This is the Toothless’s sleek black texture!”;
@Override
public String getDescription() { return DESCRIPTION;
} }
/*******************************************************************/ /* StormflyTexture.java */ /********************************************************************/ package ilovedragons;
/** *
* StormflyTexture
*
*/
public class StormflyTexture implements Texture {
static final String DESCRIPTION = “This is Stormfly’s colourful, bumpy texture!”;
@Override
public String getDescription() { return DESCRIPTION;
} }
4/5
/*******************************************************************/ /* Firebreath.java */ /********************************************************************/ package ilovedragons;
/** *
* Firebreath interface
*
*/
public interface Firebreath { String getDescription();
}
/*******************************************************************/ /* ToothlessFirebreath.java */ /********************************************************************/ package ilovedragons;
/** *
* ToothlessFirebreath
*
*/
public class ToothlessFirebreath implements Firebreath {
static final String DESCRIPTION = “This is Toothless’s fire breath (plasma blast)!”;
@Override
public String getDescription() { return DESCRIPTION;
} }
/*******************************************************************/ /* StormflyFirebreath.java */ /*******************************************************************/ package ilovedragons;
/** *
* StormflyFirebreath
*
*/
public class StormflyFirebreath implements Firebreath {
static final String DESCRIPTION = “This is the Stormfly’s fire breath!”;
@Override
public String getDescription() { return DESCRIPTION;
} }
5/5