# Student, Instructor, Classroom * **Purpose** - to demonstrate the use of [Java interfaces](http://tutorials.jenkov.com/java/interfaces.html) * **Objective** - to implement a `ZipCodeWilmington` _singleton_ which _mediates_ a _composite_ `Students` and `Instructors` reference. # Part 1.1 - Create `Person` Class * Create a `Person` class. * The class should declare a `final` field named `id` of type `long`. * `Person` constructor should have a parameter of type `long` which sets the `id` field to the respective value. * The class should define a `getId()` method which returns the `Person` object's `id` field. * The class should define a `getName()` method which returns the `Person` object's `name` field. * The class should define a `setName()` method which sets the `Person` object's `name` field. - # Part 1.0 - Test `Person` * Create a `TestPerson` class. * Create a `testConstructor` method which ensures that a `Person` object's `id` field is being set upon construction. * Create a `testSetName` method which ensures that a `Person` object's `name` variable is being set by invoking the `.setName` method. * Create a `testConstructor` method which ensures that a `Person` object's `name` variable is being set by invoking the `Person` constructor. - # Part 2.0 - Create `Learner` Interface * Create a `Learner` interface. * `Learner` should declare one method signature: * Method name: `learn` * Method parameters: `double numberOfHours` * Method return-type: `void` - # Part 3.1 - Create `Student` Class * Create a `Student` class such that: * `Student` is a subclass of `Person` * `Student` implements the `Learner` interface * `Student` should have an instance variable `totalStudyTime` of type `double` * `Student` should have a concrete implementation of the `learn` method which increments the `totalStudyTime` variable by the specified `numberOfHours` argument. * `Student` should have a `getTotalStudyTime()` method which returns the `totalStudyTime` instance variable. - # Part 3.0 - Test `Student` * Create a `TestStudent` class. * Create a `testImplementation` method that asserts that a `Student` is an `instanceof` a `Learner`. * Create a `testInheritance` method that asserts that a `Student` is an `instanceof` a `Person`. * Create a `testLearn` method that ensures a `Student`'s `totalStudyTime` instance variable is incremented by the specified `numberOfHours` by invoking the `.learn` method. - # Part 4.0 - Create `Teacher` Interface * Create a `Teacher` interface. * `Teacher` should declare a `teach` method signature: * Method name: `teach` * Method parameters: * `Student student` * `double numberOfHours` * Method return-type: `void` * `Teacher` should declare a `lecture` method signature: * Method name: `lecture` * Method parameters: * `Student[] student` * `double numberOfHours` * Method return-type: `void` - # Part 5.1 - Create `Instructor` Class * Create an `Instructor` class such that: * `Instructor` is a subclass of `Person` * `Instructor` implements the `Teacher` interface * `Instructor` should have a concrete implementation of the `teach` method which invokes the `learn` method on the specified `Student` object. * `Instructor` should have a concrete implementation of the `lecture` method which invokes the `learn` method on each of the elements in the specified array of `Student` objects. * `numberOfHours` should be evenly split amongst the students. * `double numberOfHoursPerStudent = numberOfHours / students.length;` - # Part 5.0 - Test `Instructor` * Create a `TestInstructor` class. * Create a `testImplementation` method that asserts that an `Instructor` is an `instanceof` a `Teacher`. * Create a `testInheritance` method that asserts that a `Instructor` is an `instanceof` a `Person`. * Create a `testTeach` method that ensures when an `Instructor` invokes the `.teach` method, a respective student's `totalStudyTime` instance variable is incremented. * Create a `testLecture` method that ensures when an `Instructor` invokes the `.teach` method, a respective student's `totalStudyTime` instance variable is incremented by the specified `numberOfHours`. - # Part 6.1 - Create `People` class * Create a `People` class. * The class should instantiate an `ArrayList` field of `Person` objects named `personList`. * The class should define a method named `add` which adds a `Person` to the `personList`. * The class should define a method named `findById` which makes use of a `long id` parameter to return a `Person` object with the respective `id` field. * The class should define a method named `remove` which makes use of a `Person person` parameter to remove a respective `Person` object. * The class should define a method named `remove` which makes use of a `long id` parameter to remove a `Person` object with the respective `id` field. * The class should define a method named `getCount` which returns the size of `oersonList`. * The class should define a method named `getArray` which returns an array representation of the `personList` field. * The class should define a named `removeAll` which clears our `personList` field. - # Part 6.0 - Test `People` * Create a `TestPeople` class. * Create a `testAdd` method which ensures that our `personList` in our `People` class populated with respective `Student` objects following invokation of the `addStudent` method. * Create a `testRemove` method which ensures that the `personList` in a `People` object is **depopulated** with a respective `Person` object following the invokation of the `remove` method. * Create a `testFindById` method which ensures that a respective `Person` object with a respective `id` field is returned upon invokation of the `findById` method on a respective `People` object. - # Part 7.1 - Create `Students` singleton * **Note:** The creation of this class will demonstrate an implementation of [singleton design pattern](https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples#eager-initialization). * Create a `Students` class. * The class should be an _unextendable_ subclass of the `People` class. * The class should _statically instantiate_ a `final` field named `INSTANCE` of type `Students`. * The class should define a _private nullary constructor_ which populates the `INSTANCE` field with respective `Student` representations of your colleagues. * Each student should have a _relatively_ unique `id` field. * The class should define a `getInstance` method which returns the `INSTANCE` field. - # Part 7.0 - Test `Students` singleton * Create a `TestStudents` class. * Create a `test` method which ensures that each of the students in your current cohort are in your `Students` singleton. - # Part 7.2 - Create `Instructors` singleton * Use `Part 7.0` and `Part 7.1` as a reference. * Create a `Instructors` singleton which represents the set of instructors at ZipCodeWilmington. * Create a `TestInstructors` class. # Part 8.1 - Create `ZipCodeWilmington` Class * Use `Part 7` as a reference. * Create a `ZipCodeWilmington` singleton. * The class should declare a field that references the instance of `Students` called `students`. * The class should declare a field that references the instance of `Instructors` called `instructors`. * The class should define a method `hostLecture` which makes use of a `long id, double numberOfHours` parameter to identify a respective `Instructor` to host a `lecture` to the composite `people` field in the `cohort` reference. - # Part 8.0 - Test `ZipCodeWilmington` * Create a `TestZipCodeWilmington` class. * Create a `testHostLecture` method which ensures that each of the `Student`'s `totalStudyTime` instance variable is incremented by the specified `numberOfHours` upon invoking the `.hostLecture` method. - # Notice the Design Flaw * You may have notice that `findById` makes it difficult to intuitively identify _which_ `Person` object is being returned.
Additionally, it's challengaing to ensure **every** `Person` instance has a unique ID amongst its respective `People` subclass.
To remedy this issue, we redesign and refactor. Visit the [enum microlab]()