Show
with line numbers
// Student.java - A demo of using optional constructor arguments by
// using the "constructor builder pattern". Student objects represent
// students enrolled in a college course and have many attributes.
// With more than a few, multiple constructors become hard to use well.
// The alternative of the "JavaBean" pattern (of providing "getters" and
// "setters" for each attribute) allows for inconsistant states and
// prevents immutable objects (desirable when possible).
//
// The builder "helper" class is nested within the Student class,
// to allow it access to the single private Student constructor. The
// only way to construct a Student is to create a Builder, set the
// optional values, then call Builder.build method.
//
// Also notice how each method of the builder returns the (modified)
// builder. This allows the method calls to be "chained", simulating
// named optional parameters.
// (Validity checking of arguments and other details omitted for clarity.)
//
// Written 5/2008 by Wayne Pollock, Tampa Florida USA. All Rights Reserved.
class Student
{
private static int nextStudentID;
static {
// Typically fetched from a DB at application (JVM) startup:
// ...
nextStudentID = ...;
}
// Add a shutdown hook to save the current value of nextStudentID
// to the DB when the application (the JVM) exits:
// ...
private int studentID;
private String lastName;
private String firstName;
private String address;
private String homePhone;
private int level; // 1 = freshman, ...
private Date enrolled;
private char gender; // 'M' or 'F', 'U' = unknown
// ...
// Single private Student constructor:
private Student ( Builder builder )
{
studentID = builder.studentID;
lastName = builder.lastName;
firstName = builder.firstName;
address = builder.address;
homePhone = builder.homePhone;
level = builder.level;
enrolled = builder.enrolled;
gender = builder.gender;
}
// Nested class:
public static class Builder
{
// Required Parameters:
private final int studentID;
private String lastName;
// Optional Parameters (initialized to default values):
private String firstName = "";
private String address = "unknown";
private String homePhone = "unknown";
private int level = 1;
private Date enrolled = new Date();
private char gender = 'U';
// Public builder constructor, with required parameter:
public Builder ( String lastName )
{ this.studentID = nextStudentID;
++nextStudentID;
this.lastName = lastName;
}
// Public builder methods for optional paramerers (simulates
// named parameters):
public Builder firstName ( String arg )
{ firstName = arg; return this; }
public Builder address ( String arg )
{ address = arg; return this; }
public Builder homePhone ( String arg )
{ homePhone = arg; return this; }
public Builder level ( int arg )
{ level = arg; return this; }
public Builder enrolled ( Date arg )
{ enrolled = arg; return this; }
public Builder gender ( char arg )
{ gender = arg; return this; }
// Public build method, called after setting the optional fields:
public Student build () { return new Student( this ); }
}
// public Student methods go here:
// ...
}
// Sample use (all the above complexity is so we can do this):
class StudentTest
{
Student s = new Student.Builder("Piffl").firstName("Hymie").
level(4).build();
// ...
}