if the constructor were made public I would then have to validate the student, using a private method, to ensure that if the student is domestic, the client can't pass a list of documents by throwing an exception. The static methods allowed the creation of the student objects and the client can't pass a List documents for domestic students, and there is no need to throw an exception.
This assumption is simply wrong because your factory method does not check any argument. So there is no difference whether you create your Student
objects vis your factory method or not.
On the other hand having a factory method that really checks consistency of the parameters is a good practice. But there is no need to have that in the class itself and therefor it does not need to be static
. Especially if you do not take all the parameters in one method but provide a separate setter for each. The name for is Builder Pattern.
StudenBuilder{
private String id;
private String firstname;
private String lastname;
private Collection<String> documents;
private StudentType typeofStudent;
public StudenBuilder withId(String id){
this.id=id;
return this;
}
public StudenBuilder withFirstname(String firstname){
this.firstname=firstname;
return this;
}
public StudenBuilder withLastname(String lastname){
this.lastname=lastname;
return this;
}
public StudenBuilder with(Collection<String> documents ){
Collections.unmodifiableList(new ArrayList<String>(documents));
return this;
}
public StudenBuilder withStudentType(StudentType typeofStudent ){
this.typeofStudent=typeofStudent;
return this;
}
public Student build(){
// check consistency
// e.g. require documents for a certain StudentType
return new Student(id, firstname, lastname, documents, typeofStudent);
}
}
The usage would look like this:
Student newStudent = new StudentBuilder()
.withId("someId")
.withFirstName("some first name")
.withLastName("some last name")
.withStudentType(StudentType.SOME)
.build();