Download Final Exam (Take Home)

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Final Exam (Take Home)
CS 414 Object-Oriented Design, Fall 2012
Honor Pledge
“I have not given, received, or used any unauthorized assistance.”
Signed: Brock Wilcox
(1)
(a) Activity diagram
(b) Use case diagram
(c) Use Cases
Modify Appointment
actor: registered Patient
Modify Appointment
Scope: Online Medical Appointment Scheduling System
Level: User goal
Primary Actor: Registered Patient
Stakeholders and Interests:
• Patient wants high usability
• Doctor wants to avoid conflicts and to keep their schedule updated
Preconditions: User is authenticated and has an existing appointment
Basic Flow:
1. User views list of appointments
2. User selects appointment to be modified
3. User indicates what type of modification they want
4. User enters updated details (new date, service, doctor)
5. System confirms to the user that their appointment has been changed
Alternative Flow:
5a. Doctor is not available at that time
1. System notifies user that the doctor is unavailable
2. System notifies user of next-closest availability
3. System notifies user of other available doctors for the given time
4. Allow user to re-enter desired updated details, returning to basic flow 4
View Appointment Schedule
Scope: Online Medical Appointment Scheduling System
Level: User goal
Primary Actor: Doctor
Stakeholders and Interests:
• Patient wants doctors to show up
• Doctor wants to avoid conflicts and to keep their schedule updated
Preconditions: Doctor is authenticated
Basic Flow:
1. Doctor enters date range
2. Doctor specifies schedule type (summary, detail)
3. System produces a schedule report
Alternative Flow:
1a. Doctor enters invalid date range
1. System notifies doctor of invalid date range
2. System allows doctor to re-enter date range, returning to basic flow 1
(2)
(a)
* Add class for each state
* Move Method from machine to state class
* Create base class with exception for each action
* Create method in machine for each action
*** RentalStateMachine.java with State Pattern ***
1 class IllegalEventException extends Exception { }
2
3 public class RentalStateMachine {
4
private RentalState currentState;
5
public void rent() throws IllegalEventException {
6
currentState = currentState.rent();
7
}
8
public void setForSale() throws IllegalEventException {
9
currentState = currentState.setForSale();
10 }
11 public void sell() throws IllegalEventException {
12
currentState = currentState.sell();
13 }
14 public void returnRental() throws IllegalEventException {
15
currentState = currentState.returnRental();
16 }
17 }
18
19 class RentalState {
20 RentalState rent() throws IllegalEventException {
21
throw new IllegalEventException();
22 }
23 RentalState setForSale() throws IllegalEventException {
24
throw new IllegalEventException();
25 }
26 RentalState sell() throws IllegalEventException {
27
throw new IllegalEventException();
28 }
29 RentalState returnRental() throws IllegalEventException {
30
throw new IllegalEventException();
31 }
32 }
33
34 class ForRent extends RentalState {
35 public RentalState rent() throws IllegalEventException {
36
return new Rented();
37 }
38 public RentalState setForSale() throws IllegalEventException {
39
return new ForSale();
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
}
}
class ForSale extends RentalState {
public RentalState sell() throws IllegalEventException {
return new Sold();
}
}
class Rented extends RentalState {
public RentalState returnRental() throws IllegalEventException {
return new ForRent();
}
}
class Sold extends RentalState {
}
(b)
*** RentalStateMachine.java with State Pattern with Withdrawn ***
1 class IllegalEventException extends Exception { }
2
3 public class RentalStateMachine {
4
private RentalState currentState;
5
public void rent() throws IllegalEventException {
6
currentState = currentState.rent();
7
}
8
public void setForSale() throws IllegalEventException {
9
currentState = currentState.setForSale();
10 }
11 public void sell() throws IllegalEventException {
12
currentState = currentState.sell();
13 }
14 public void returnRental() throws IllegalEventException {
15
currentState = currentState.returnRental();
16 }
17 public void withdraw() throws IllegalEventException {
18
currentState = currentState.withdraw();
19 }
20 }
21
22 class RentalState {
23 RentalState rent() throws IllegalEventException {
24
throw new IllegalEventException();
25 }
26 RentalState setForSale() throws IllegalEventException {
27
throw new IllegalEventException();
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
}
RentalState sell() throws IllegalEventException {
throw new IllegalEventException();
}
RentalState returnRental() throws IllegalEventException {
throw new IllegalEventException();
}
RentalState withdraw() throws IllegalEventException {
throw new IllegalEventException();
}
}
class ForRent extends RentalState {
public RentalState rent() throws IllegalEventException {
return new Rented();
}
public RentalState setForSale() throws IllegalEventException {
return new ForSale();
}
public RentalState withdraw() throws IllegalEventException {
return new Withdrawn();
}
}
class ForSale extends RentalState {
public RentalState sell() throws IllegalEventException {
return new Sold();
}
public RentalState withdraw() throws IllegalEventException {
return new Withdrawn();
}
}
class Rented extends RentalState {
public RentalState returnRental() throws IllegalEventException {
return new ForRent();
}
}
class Sold extends RentalState {
}
class Withdrawn extends RentalState {
RentalState rent() throws IllegalEventException {
return this;
}
RentalState setForSale() throws IllegalEventException {
return this;
}
77 RentalState sell() throws IllegalEventException {
78
return this;
79 }
80 RentalState returnRental() throws IllegalEventException {
81
return this;
82 }
83 RentalState withdraw() throws IllegalEventException {
84
return this;
85 }
86 }
87
(c)
*** RentalStateMachine.java with Withdrawn ***
1 public class RentalStateMachine {
2
public enum RentalState {
3
ForRent, Rented, ForSale, Sold, Withdrawn;
4
}
5
private RentalState currentState;
6
public void rent() throws IllegalEventException {
7
if(currentState == RentalState.Withdrawn) {
8
return;
9
}
10
if(currentState == RentalState.ForRent) {
11
currentState = RentalState.Rented;
12
} else {
13
throw new IllegalEventException();
14
}
15 }
16 public void returnRental() throws IllegalEventException {
17
if(currentState == RentalState.Withdrawn) {
18
return;
19
}
20
if(currentState == RentalState.Rented) {
21
currentState = RentalState.ForRent;
22
} else {
23
throw new IllegalEventException();
24
}
25 }
26 public void setForSale() throws IllegalEventException {
27
if(currentState == RentalState.Withdrawn) {
28
return;
29
}
30
if(currentState == RentalState.ForRent) {
31
currentState = RentalState.ForSale;
32
} else {
33
throw new IllegalEventException();
34
}
35 }
36 public void sell() throws IllegalEventException {
37
if(currentState == RentalState.Withdrawn) {
38
return;
39
}
40
if(currentState == RentalState.ForSale) {
41
currentState = RentalState.Sold;
42
} else {
43
throw new IllegalEventException();
44
}
45 }
46 public void withdraw() {
47
if(currentState == RentalState.Withdrawn) {
48
return;
49
}
50
if(currentState == RentalState.ForRent){
51
currentState = RentalState.Withdrawn;
52
} else if(currentState == RentalState.ForSale){
53
currentState = RentalState.Withdrawn;
54
} else {
55
throw new IllegalEventException();
56
}
57 }
58 }
(d)
Touched 24 lines across 5 methods to add the new state to the original.
Touched 28 lines across 5 methods to add the new state to the state pattern code.
However – the code that was added to the state pattern code was much more contained. The
modifications for the original was code that was added to the middle of methods, and the
compiler gave no help for detecting errors. In the state pattern code the new code was mostly
new independent methods for handling the transitions.
(3)
•
•
•
•
•
•
•
Extract/Move method evaluate into base Node class
Add IdentifierToValue to Node evaluate method
One by one, starting with the 'Token' block, copy that leg of the conditional into the
given class as an override to evaluate
restructure local method invocation, such as 'token.getText' to just 'getText'
restructure recursive invocation of 'evaluate' to be a method invocation, like
getLeft().evaluate(IdentifierToValue)
Compile between each, which will say which ones remain, then remove that part of the
conditional
Once all pieces of the conditional are copied into Node subclasses as overrides, make
the superclass abstract (it will now be empty, so remove entire body).
Resulting code:
*** Addition.java ***
1
2 public class Addition extends Expression {
3
public int evaluate(java.util.HashMap<String, Integer> IdentifierToValue){
4
int leftOperand = getLeft().evaluate(IdentifierToValue);
5
int rightOperand = getRight().evaluate(IdentifierToValue);
6
return leftOperand+rightOperand;
7
}
8}
*** Evaluator.java ***
1
2 import java.util.*;
3 public class Evaluator {
4
private HashMap<String, Integer> IdentifierToValue;
5
public int evaluate(Node node){
6
return node.evaluate(IdentifierToValue);
7
}
8}
*** Expression.java ***
1
2 public abstract class Expression extends Node {
3
private Node left;
4
private Node right;
5
public Node getLeft(){
6
return left;
7
}
8
public Node getRight(){
9
return right;
10
}
11
12 }
*** Negate.java ***
1
2 public class Negate extends Expression {
3
public int evaluate(java.util.HashMap<String, Integer> IdentifierToValue){
4
int leftOperand = getLeft().evaluate(IdentifierToValue);
5
return (-leftOperand);
6
}
7}
*** Node.java ***
1
2 public abstract class Node {
3
abstract public int evaluate(java.util.HashMap<String, Integer> IdentifierToValue);
4}
5
*** Subtraction.java ***
1
2 public class Subtraction extends Expression{
3
public int evaluate(java.util.HashMap<String, Integer> IdentifierToValue){
4
int leftOperand = getLeft().evaluate(IdentifierToValue);
5
int rightOperand = getRight().evaluate(IdentifierToValue);
6
return leftOperand-rightOperand;
7
}
8}
*** Token.java ***
1
2 public class Token extends Node {
3
public static final int IDENTIFIER = 1;
4
public static final int INTEGER_LITERAL = 2;
5
private int type;
6
private String text;
7
public String getText(){
8
return text;
9
}
10
public int getType(){
11
return type;
12
}
13
public int evaluate(java.util.HashMap<String, Integer> IdentifierToValue){
14
int type = getType();
15
if(type == Token.IDENTIFIER)
16
return IdentifierToValue.get(getText()).intValue();
17
else
18
return Integer.parseInt(getText());
19
}
20 }
(4)
(5)
After first change (part a), adding controller:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import
import
import
import
javax.swing.*;
java.awt.*;
java.awt.event.*;
java.util.HashMap;
class SaleFrame extends JFrame implements ActionListener {
private SaleController controller;
private
private
private
private
JButton enterItemButton
JTextField priceField
JTextField itemIDField
JTextField quantityField
=
=
=
=
new
new
new
new
JButton("Enter Item");
JTextField(30);
JTextField(10);
JTextField(10);
public SaleFrame(SaleController c) {
controller = c;
Container container = getContentPane();
container.setLayout(new FlowLayout(FlowLayout.CENTER));
container.add(new JLabel("Enter Item ID(1/2)"));
container.add(itemIDField);
container.add(new JLabel("Enter quantity of the item"));
container.add(quantityField);
container.add(enterItemButton);
container.add(new JLabel("The total price of the item"));
container.add(priceField);
priceField.setEditable(false);
enterItemButton.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
controller.enterItem(itemIDField.getText(), quantityField.getText());
}
public void displayPrice(int price) {
priceField.setText("The price for the entered item is "+ price);
}
}
public class SaleController {
private SaleFrame saleframe;
public SaleController() {
saleframe = new SaleFrame(this);
saleframe.setSize(200, 200);
saleframe.setVisible(true);
}
public void enterItem(String item_id_text, String quantity_text) {
ProductCatalog productCatalog = ProductCatalog.getInstance();
int itemID = Integer.parseInt(item_id_text);
ProductDescription description =
productCatalog.getProductDescription(itemID);
PriceCalculator calculator = new PriceCalculator();
int quantity = Integer.parseInt(quantity_text);
calculator.calculatePrice(quantity, description, saleframe);
}
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
public static void main(String [] args) {
SaleController controller = new SaleController();
// PriceCalculator calculator = new PriceCalculator();
// calculator.add_listener(saleframe);
}
}
class ProductCatalog {
private HashMap<Integer, ProductDescription> itemIDtoProductDescriptionMap
= new HashMap<Integer, ProductDescription>();
protected ProductCatalog() {
super();
itemIDtoProductDescriptionMap.put(1, new ProductDescription(10));
itemIDtoProductDescriptionMap.put(2, new ProductDescription(15));
}
private static ProductCatalog INSTANCE;
public static ProductCatalog getInstance() {
if (INSTANCE != null)
return INSTANCE;
else
return new ProductCatalog();
}
public ProductDescription getProductDescription(int itemID) {
return itemIDtoProductDescriptionMap.get(itemID);
}
}
class ProductDescription {
private int unitPrice;
public ProductDescription(int unitPrice) {
this.unitPrice = unitPrice;
}
public int getUnitPrice() {
return unitPrice;
}
}
class PriceCalculator {
public void calculatePrice(int quantity, ProductDescription description,
SaleFrame frame) {
int price = quantity*description.getUnitPrice();
frame.displayPrice(price);
}
}
After second change (part b), adding observer pattern:
1
2 import javax.swing.*;
3 import java.awt.*;
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.awt.event.*;
import java.util.*;
class SaleFrame extends JFrame implements ActionListener, Observer {
private SaleController controller;
private
private
private
private
JButton enterItemButton
JTextField priceField
JTextField itemIDField
JTextField quantityField
=
=
=
=
new
new
new
new
JButton("Enter Item");
JTextField(30);
JTextField(10);
JTextField(10);
public SaleFrame(SaleController c) {
controller = c;
Container container = getContentPane();
container.setLayout(new FlowLayout(FlowLayout.CENTER));
container.add(new JLabel("Enter Item ID(1/2)"));
container.add(itemIDField);
container.add(new JLabel("Enter quantity of the item"));
container.add(quantityField);
container.add(enterItemButton);
container.add(new JLabel("The total price of the item"));
container.add(priceField);
priceField.setEditable(false);
enterItemButton.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
controller.enterItem(itemIDField.getText(), quantityField.getText());
}
public void displayPrice(int price) {
priceField.setText("The price for the entered item is "+ price);
}
public void update(Observable o, Object arg) {
System.out.println("Updating...");
Integer price = (Integer) arg;
displayPrice(price);
}
}
public class SaleController {
private SaleFrame saleframe;
private PriceCalculator calculator;
public SaleController() {
saleframe = new SaleFrame(this);
saleframe.setSize(200, 200);
saleframe.setVisible(true);
calculator = new PriceCalculator();
calculator.addObserver(saleframe);
System.out.println("Added observer.");
}
public void enterItem(String item_id_text, String quantity_text) {
ProductCatalog productCatalog = ProductCatalog.getInstance();
int itemID = Integer.parseInt(item_id_text);
ProductDescription description =
productCatalog.getProductDescription(itemID);
int quantity = Integer.parseInt(quantity_text);
calculator.calculatePrice(quantity, description);
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
}
public static void main(String [] args) {
SaleController controller = new SaleController();
}
}
class ProductCatalog {
private HashMap<Integer, ProductDescription> itemIDtoProductDescriptionMap
= new HashMap<Integer, ProductDescription>();
protected ProductCatalog() {
super();
itemIDtoProductDescriptionMap.put(1, new ProductDescription(10));
itemIDtoProductDescriptionMap.put(2, new ProductDescription(15));
}
private static ProductCatalog INSTANCE;
public static ProductCatalog getInstance() {
if (INSTANCE != null)
return INSTANCE;
else
return new ProductCatalog();
}
public ProductDescription getProductDescription(int itemID) {
return itemIDtoProductDescriptionMap.get(itemID);
}
}
class ProductDescription {
private int unitPrice;
public ProductDescription(int unitPrice) {
this.unitPrice = unitPrice;
}
public int getUnitPrice() {
return unitPrice;
}
}
class PriceCalculator extends Observable {
public void calculatePrice(int quantity, ProductDescription description) {
int price = quantity*description.getUnitPrice();
System.out.println("Notifying...");
setChanged();
notifyObservers(price);
System.out.println("done notifying.");
}
}
Related documents