To recover from yesterday's disaster, I re-read the SOLID principles and refactored my code. Hopefully I did a better job than yesterday. I wanted to keep my Student
class immutable, but that meant I would have to change the class every time a new Student
type was introduced, that violated the S in SOLID. Here is what I came up with.
public interface StudentStatus {
Collection<String> retrieveDocuments();
StudentType retrieveStatus();
}
public final class Student {
private final String ID;
private final String firstname;
private final String lastname;
private final StudentStatus status;
public Student(String iD, String firstname, String lastname, StudentStatus status) {
ID = iD;
this.firstname = firstname;
this.lastname = lastname;
this.status = status;
}
public Collection<String> retrieveDocuments() {
return status.retrieveDocuments();
}
public StudentType retrieveStatus() {
return status.retrieveStatus();
}
My requirements are:
- Domestic students don't require documentation
- International student do require documentation (passports, etc..)
Domestic Implementation:
public final class Domestic implements StudentStatus {
private final StudentType type;
private final Collection<String> documents;
public Domestic() {
this.type = StudentType.Domestic;
this.documents = unmodifiableList(new ArrayList<String>(documents);
}
@Override
public Collection<String> retrieveDocuments() {
return unmodifiableList(new ArrayList<String>(documents);
}
@Override
public StudentType retrieveStatus() {
return type;
}
}
International Implementation:
public final class International implements StudentStatus {
private final StudentType type;
private Collection<String> documents;
public International(Collection<String> documents) {
this.type = StudentType.International;
this.documents = Collections.unmodifiableList(new ArrayList<String>(documents));
}
@Override
public Collection<String> retrieveDocuments() {
return Collections.unmodifiableList(new ArrayList<String>(documents));
}
@Override
public StudentType retrieveStatus() {
return type;
}
}
If there is any new type of status, it can be added my implementing StudentStatus
, no need to modify the Student
class.
Use:
List<String> documents = new ArrayList<String>();
documents.add("Passport");
documents.add("Drivers License");
StudentStatus domestic = new Domestic();
StudentStatus international = new International(documents);
List<Student> students = new ArrayList<Student>();
students.add(new Student("123456789","Susan","Ceesharp", domestic));
students.add(new Student("987654321","Bill","Finalclass", international));
for(Student display : students) {
System.out.println(display.getID() + " " + display.retrieveStatus());
}
I'm aware none of my classes have validation, I kept these out to keep my code clear and concise.
Goal:
Keep the Student
immutable without violating SOLID.