Creating a Student class for a project 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&lt;String&gt; 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&lt;String&gt; 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&lt;String&gt; documents;

       public Domestic() {
           this.type = StudentType.Domestic;
           this.documents = unmodifiableList(new ArrayList&lt;String&gt;(documents);
       }

       @Override
       public Collection&lt;String&gt; retrieveDocuments() {
           return unmodifiableList(new ArrayList&lt;String&gt;(documents);
       }

       @Override
       public StudentType retrieveStatus() {
           return type;
       }
   }


International Implementation:

    public final class International implements StudentStatus {

       private final StudentType type;
       private Collection&lt;String&gt; documents;

       public International(Collection&lt;String&gt; documents) {

           this.type = StudentType.International;
           this.documents = Collections.unmodifiableList(new ArrayList&lt;String&gt;(documents));
       }

       @Override
       public Collection&lt;String&gt; retrieveDocuments() {
           return Collections.unmodifiableList(new ArrayList&lt;String&gt;(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&lt;String&gt; documents = new ArrayList&lt;String&gt;();
        documents.add("Passport");
        documents.add("Drivers License");

        StudentStatus domestic = new Domestic();
        StudentStatus international = new International(documents);

        List&lt;Student&gt; students = new ArrayList&lt;Student&gt;();
        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.
As a minor note you could change this.documents = unmodifiableList(new ArrayList&lt;String&gt;(documents); to this.documents = Collections.emptyList();