Student, Instructor, Classroom

  • Purpose - to demonstrate the use of Java interfaces
  • 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 personList.
    • 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.
  • 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 8.0 - Create and Test Instructors singleton

  • Use Part 7 as a reference.
  • Create a Instructors singleton which represents the set of instructors at ZipCodeWilmington.
  • Create a TestInstructors class.

Part 9.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 Teacher teacher, double numberOfHours parameter to host a lecture to the composite people field in the students reference.
    • 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 9.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 - Odd Casting Issues

  • You may have noticed that the findById, and hostLecture methods require an intermediate casting trick.
  • To remedy this issue, we can generify the People class.

Part 10.1 - Modify People class

  • Parameterize the People signature to enfore that it is a container for objects of type E such that E is a subclass of Person.
  • Modify people field to enforce that is a container of objects of type E.
  • Modify the add method to ensure that it handles object of type E.
  • Modify the getArray method to ensure that it returns an object of type E[].
  • Modify the findById method to ensure that it returns an object of type E.

Part 10.2 - Modify People subclasses

  • Modify the Students class signature to ensure that it is a subclass of People of parameterized type Student.
  • Modify the Instructors class signature to ensure that it is a subclass of People of parameterized type Instructor.

Part 10.3 - Refactor ZipCodeWilmington class

  • Refactor the hostLecture method in the ZipCodeWilmington class by removing any intermediate casting trick(s).

Part 10.0 - Test refactored classes.

  • Ensure that the TestStudents, TestInstructors, TestPeople, TestZipCodeWilmington classes were no affected by the refactor.

-

Notice the Design Flaw - Non-Intuitive Orientation

  • You may have notice that findById makes it difficult to intuitively identify which Person object is being returned.
    Additionally, it's challenging to ensure every Person instance has a unique ID amongst its respective People subclass.
    To remedy this issue, we redesign and refactor.

Part 11.1 - Create Educator enum

  • Create an enum named Educator.
    • The enum should implement Teacher.
    • The enum should have an enumeration for each of the instructors represented in the Instructors class.
    • The enum should have an empty nullary constructor.

Part 11.0 - Test Educator

  • Use Part 5 as a reference.

Part 12.1 - Modify Instructor Class

  • Annotate the constructor with @Deprecated.
  • This constructor should be commented with //TODO - Remove dependencies
  • Create a constructor in the Instructor class which uses Educator educator parameter to set a final educator field.
  • The class should differ calls to the teach and lecture method to the composite educator field.
  • Remove any calls being made to the deprecated construcor.
  • Remove the deprecated constructor from the class.

Part 12.0 - Test Instructor

  • Refactor TestInstructor to support the newly created Instructor constructor.
  • Ensure the tests were not affected by the refactoring.