/home/wpollock1/public_html/AJava/StudentBuilderDemo.java
// 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.
// Updated 3/2021: Replaced mutable Date with immutable LocalDate.
import java.time.*;
class Student
{
private static int nextStudentID;
static {
// Typically fetched from a DB at application (JVM) startup:
// nextStudentID = ...;
nextStudentID = 1; // For demo purposes
}
// 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 LocalDate enrolled;
// ...
// 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;
}
// 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 LocalDate enrolled = LocalDate.now();
// Public builder constructor, with required parameter:
public Builder ( String lastName )
{ this.studentID = nextStudentID;
++nextStudentID;
this.lastName = lastName;
}
// Public builder methods for optional parameters (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 ( LocalDate arg )
{ enrolled = arg; return this; }
// Public build method, called after setting the optional fields:
public Student build () { return new Student( this ); }
}
// public Student methods go here:
// ...
// Display all fields & values (for demo purposes):
public String toString () {
return "studentID: " + studentID +
"\nlastName: " + lastName +
"\nfirstName: " + firstName +
"\naddress: " + address +
"\nhomePhone: " + homePhone +
"\nlevel: " + level +
"\nenrolled: " + enrolled;
}
}
// Sample use (all the above complexity is so we can do this):
public class StudentBuilderDemo
{
public static void main ( String [] args ) {
Student s = new Student.Builder("Piffl").firstName("Hymie").
level(4).build();
// ...
System.out.println( s ); // For demo purposes
}
}