// 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(); // ... }