Homework 5 - Strategy Pattern for Abstract Data Types &
Encapsulation
Due Tuesday by 11:59pm
Points 70
Submitting an external tool
Disclaimer: This homework is involved, but uses code you should already know from HW3 and
HW4. Please carefully read the entire assignment to understand what you are supposed to add
and what starter code you have to use.
Summary
A startup for backyard farming wants you to combine your work on HW3 and HW4 for their
greenhouse sensor networks.
You will be writing code for a class that maintains a mutable datetime object called a
GregorianCalendar (https://docs.oracle.com/javase/8/docs/api/java/util/GregorianCalendar.html) .
Rogue botanists are trying to hack the sensor network with incorrect data after the fact, and the
datetime object is intended to help prevent that.
You will design a Strategy (you get to pick the methods!) for adding TempHumidRTPByDate-like
objects to a data structure and querying it with some constraints.
You will then implement the strategy at least twice:
With a list class of your choosing
With an AVL tree using the AVLStrategy.
[Note: after this homework, Prof. Ahrens strongly discourages the use of the Gregorian Calendar
object. You'll see that is is a pain because of its poor design choices (it was in use until Java 6.0!)
and its mutability. We are using its poor design as a learning tool here, but in real production code,
you would want to use java.util.time.]
(https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html)
Learning Objectives:
Students will be able to
Encapsulate a mutable field (GregorianCalendar) to prevent unintended access or mutation
from outside of our class' score.
Homework 5 - Strategy Pattern for Abstract Data Types & Encapsulation
1/9
Design a Strategy for an Abstract Data type that allows adding, querying, and changing from
one to another.
Use method overloading (when appropriate) to vary method behavior based on different types
of parameters
Extend existing code on what would be considered a "small-to-medium" sized project with
several class files
Extend a class to implement the Comparable<T> interface
Implement Binary Search using recursion on a tree-like structure in Java
Overview
Primary data structure
The primary class you will implement is GreenHouse.java which will:
implement IGreenHouse
it should not extend or inherit from anything (we are using the strategy pattern instead)
Encapsulate a GregorianCalendar field and an IGHStrategy field (make them private)
Consume a GregorianCalendar object as a parameter to its constructor to initialize the field
implement void intakeData(List<Double> data) similar to HW3 inside of many
TempHumidRTPByDate objects except:
it ignores data that is dated strictly before (<) the field's current date to avoid data tampering
it will ask the strategy field to add the data for the non-ignored dates
it updates its gregorian calendar field to the most recent, non-ignored date in the data
if all the data was ignored, the gregorian calendar field is not updated
implement the two maxTemperature(...) and two minHumidity(...) methods declared on
IGreenHouse.java (look at the javadocs on the interface for information about each method)
implement setStrategy(IGHStrategy other) which:
makes the current strategy give all of its data to the other strategy
replaced the current strategy with the other strategy
important! IGreenHouse provides helper methods you can call from GreenHouse.java using
the keyword this for converting between GregorianCalendar objects and yyyymmdd.0 style date
doubles.
The GreenHouse sets its strategy field to GHStrategyList by default
In general, the code as shown in the tests will work like this:
Make a gregorian calendar for a date
Make a greenhouse and give it that gregorian calendar
Make the greenhouse intake data
It should parse out all the dates
It should ignore data from dates before its current gregorian calendar date
Homework 5 - Strategy Pattern for Abstract Data Types & Encapsulation
2/9
It should give each date and the data to its strategy which will store the data in some data
structure full of TempHumidRTPByDate objects (or subclasses thereof)
When asked for maxTemperature(forDate)/minHumidity(forDate)
it should ask the strategy for data to help it compute the answer from the strategy's data
structure
When asked for maxTemperature()/minHumidity()
it should ask the strategy for data to help it compute the answer from the strategy's data
structure
and provide it the current date of the gregorian calendar to do so
When asked to set its strategy to a new AVLStrategy()
The current List strategy should give its data to the AVLStrategy object
the greenhouse should set its field to the AVLStrategy object
Strategy hiding an abstract data type
You will also implement the interface IGHStrategy.java with two strategy classes:
GHStrategyList.java
should have a 0-arg constructor
Should store the data as a List
It is recommended you make this class have a list as a field, but you may extend
LinkedList<T> or ArrayList<T> instead if you like
GHStrategyAVL.java
should have a 0-arg constructor
Should store the data in an AVL tree.
you can make this class have an AVL tree as a field or you may extend BinaryTree<T>
directly
Make sure to initialize the binary tree with the StrategyAVL
You may intialize the validator as the ValidatorBTDefault to speed up adding elements
e.g.,
public class GHStrategyAVL extends BinaryTree<ELEMENT TYPE GOES HERE>
implements IGHStrategy
The GreenHouse should not care what data structure is used.
Element Type:
For both the List and AVL strategies, you must choose TempHumidRTPByDate as your element
type, but to do so, you can extend it with a new class
Call it whatever you like
Make it implement Comparable like:
public class CLASSNAME extends TempHumidRTPByDate implements
Homework 5 - Strategy Pattern for Abstract Data Types & Encapsulation
3/9
Comparable<CLASSNAME>
Replace CLASSNAME with whatever you would like to call it.
Implement public int compareTo(CLASSNAME other) such that you are comparing just
their dates
You may also benefit from implementing public int compare(double date) as well as
overriding toString() to just print out the date.
It is recommended to implement a method to help you merge two of these objects into one if
their dates match
For any strategy, if the date is already in the List/Tree, then the data should be merged into a
single element rather than having multiple elements with the same date.
You get to pick what methods IGHStrategy defines to do the job with the following rules:
An IGHStrategy should never return/get/expose its datastructure (List, BST, etc.) to the client.
An IGHStrategy should never "flatten" its data structure (e.g. return a list of its elements)
It should have methods that GreenHouse can use to do what it needs to do regardless of data
structure choice.
The strategy should never have access to the gregorian calendar field on greenhouse
Basically, you may decide how much or how little work the strategy should do when making
TempHumidRTPByDate objects, but GreenHouse should be the only one manipulating the
gregorian calendar and the strategy should be the only one manipulating the data structure (List,
Tree, etc.)
There are multiple correct answers and you may need to revise your design throughout the
homework.
Hints for strategy methods
setStrategy(...)
To make one strategy give its data to another, you can define a method that you can call
like strat1.giveAllTo(strat2) since strat1 will be able to traverse its data structure. For this to work
easily, the strategy needs to be able to add TempHumidRTPByDate (or their subclasses) objects to
itself.
Looking up your TempHumidRTPByDate subclass objects in the strategy
GHStrategyList can simply store the data unsorted, but then search through the list looking for the
appropriate date when looking them up.
GHStrategyAVL should store them using the AVL addElt() where Comparable<> will make the
subclass objects sorted by date, but then look them up using a recursive method that utilizes the
BST invariant. The reference solution implements such a method that returns an Optional<> (to
handle if the tree is empty or if the date cannot be found).
Homework 5 - Strategy Pattern for Abstract Data Types & Encapsulation
4/9
Optional<>
The methods from Optional that you will likely need are:
Optional.empty() // static method that makes an empty optional
Optional.of(elt) // static method that makes a present optional
optionalObject.isEmpty()
optionalObject.isPresent()
optionalObject.get() // only use if the optional object is not empty (is present)
Human Graded - Encapsulation
The constructor of the GreenHouse should not set its field to the given GregorianCalendar
directly
Someone who has access to the original object may mutate it (like if it was reused by multiple
green houses)
So, the constructor should make a copy some how
You can make a new Gregorian Calendar and then pass it the data from the parameter Gregorian
calendar object.
Here is how you get data out of a Gregorian calendar and make a new one:
int year = someGC.get(Calendar.YEAR);
int month = someGC.get(Calendar.MONTH);
int day someGC.get(Calendar.DAY_OF_MONTH);
new GregorianCalendar(year,month,day)
GregorianCalendar objects represent everything as zero indexed constants, including months
(oof), so
0 is January
11 is December
Human Graded - Runtime Analysis
We want to analyze our choices of data structure in terms of how many dates we have to traverse
before getting to the data we want.
In your javadoc comments for your implementations of each strategy's methods (GHStrategyList
and GHStratgyAVL), provide a runtime analysis in BigO where n is the number of dates we have
as well as a few sentences about why.
Homework 5 - Strategy Pattern for Abstract Data Types & Encapsulation
5/9
You may assume that AVL's addElt() is O(log(n)) even if it occasionally reshuffles (although
Prof. Ahrens doesn't know if his implementation actually adheres to that...)
While sorting the list of temperatures and humidities is O(m*log(m)) where m is the amount of
temperature and humidity values, since we are just analyzing how many dates we have to
traverse, you may assume getting the maxTemp/minHumidity is constant time.
Starter code
Here is starter code (https://canvas.wpi.edu/courses/57081/files/6547984?wrap=1)
(https://canvas.wpi.edu/courses/57081/files/6547984/download?download_frd=1) that contains files
from HW3 and HW4, as well as new ones for HW5:
HW3
TempHumid - interface
TempHumidTemplate - reference solution
TempHumidRTP - reference solution
TempHumidRTPByDate - reference solution
HW4
Interfaces
IBinTree
IBTStrategy
IBTValidator
Classes
BinaryTree
mutable datatype
BTEmpty & BTNode
immutable datatype
StrategyBTAbs, StrategyBST, & StrategyAVL
the add strategy we will use
ValidatorBTDefault
For efficiency, we aren't validating after each add. Live dangerously!
HW5
Interfaces
IGreenHouse - what your GreenHouse.java should implement
IGHStrategy
the starter code version is empty. Your job is to design what methods should go in it.
You may use your TempHumid* classes instead of the ones in the starter code.
What you will turn in:
GreenHouse.java
Homework 5 - Strategy Pattern for Abstract Data Types & Encapsulation
6/9
Your designed IGHStrategy.java
Your implementations of GHStrategyList.java and GHStrategyAVL.java
Your subclass of TempHumidRTPByDate that implements Comparable<...> and has any helper
methods you might need
Your TempHumid* classes if you want to use yours instead of mine
Any other classes you made to make the implementation work
Reference Solution Partial UML:
This is some of the UML for the reference solution (methods are omitted since you get to make
your own methods for IGHStrategy)
The reference solution decided to make GHStrategyList have a List<THByDateComparable> field,
but make GHStrategyAVL extend BinaryTree<THByDateComparable>. THByDateComparable is
what the reference solution called the subclass of TempHumidRTPByDate, but you may pick a
different name if you like since it is an internal implementation choice which the autograder tests
don't need to know about.
This is the reference solution's implementation of the element subclass type which implements
Comparable<> so it can be used in the BST
Homework 5 - Strategy Pattern for Abstract Data Types & Encapsulation
7/9
Rubric and Extra Credit
[40 points] Autograded
Typical use: add a bunch of data and then look up maxTemp/minHumid by date
Try and add old data: add a bunch of data, then try and add data from before the updated
GreenHouse clock's date (which should be ignored)
Try and mutate the gregorian calendar: Make a greenhouse, but then mutate the gregorian
calendar passed in from the test. GreenHouse object should be unaffected
Human Graded
[10 points] The strategies do not expose their internal structure
[10 points] The AVL strategy does not flatten its elements into a list or provide a method to
get the elements as a list
[10 points] The runtime analysis of the methods for the List and AVL implementations is
reasonably correct
Extra Credit
[5 points] Implement your strategy with a HashMap<Double, YOUR ELEMENT TYPE> such
that it maps dates (as yyyymmdd.0) doubles to your TempHumidRTPByDate subclass
HashMap get and put are practically O(1)
Write in a javadoc on the class if you had to modify your interface in order to support a
hashmap implementation (Ideally, you did not)
[2 points] Worked with a partner
[2 points] Turned it in on time (no extension used)
Homework 5 - Strategy Pattern for Abstract Data Types & Encapsulation
8/9
Autograder Results
Autograder Output
src/edu/wpi/hw5/GHStrategyAVL.java:6: error: GHStrategyAVL is not abstract and
public class GHStrategyAVL implements IGHStrategy {
^
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
An Autograder error has occurred such that none of the tests could be run.
Autograder could not be run due to an error in the submission
Code Results
Ungraded Homework 5 - Strategy Pattern for Abstract Data Types &
Encapsulation
?
Homework 5 - Strategy Pattern for Abstract Data Types & Encapsulation
9/9
请加QQ:99515681 邮箱:99515681@qq.com WX:codinghelp