SE450: Static Factory Example [44/47] Previous pageContentsNext page

Notable in the example is the different way invariants are handled.

Person checks invariants in the constructor (throwing exceptions from the factory method if necessary).

SSN checks invariants in the factory method. Exactly one instance may violate the invariants: SSN.INVALID may be used for persons with no SSN.

file:factory/person/SSN.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
package factory.person;
public interface SSN extends Comparable<SSN> {
  public String toString();
  public long toLong();
  public static final SSN INVALID = new SSNObj("000000000");
}

file:factory/person/Person.java [source] [doc-public] [doc-private]
01
02
03
04
05
package factory.person;
public interface Person extends Comparable<Person> {
  public String name();
  public SSN ssn();
}

file:factory/person/PersonFactory.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package factory.person;
import java.util.Random;
public class PersonFactory {
  private PersonFactory() {}
  static private Random random = new Random();
  static public SSN newSSN(String s) {
    final int REQUIREDLENGTH = 9;
    if (null == s || REQUIREDLENGTH != s.length())
      throw new IllegalArgumentException();
    boolean someNonZeroDigit = false;
    for (int i=0; i<REQUIREDLENGTH; i++) {
      char c = s.charAt(i);
      if (!Character.isDigit(c))
        throw new IllegalArgumentException();
      if (0 != Character.digit(c,10))
        someNonZeroDigit = true;
    }
    if (!someNonZeroDigit)
      throw new IllegalArgumentException();
    return new SSNObj(s);
  }
  static public Person newRandomPerson() {
    return new PersonObj(Integer.toString(random.nextInt()),SSN.INVALID);
  }
  static public Person newPerson(String name, String ssn) {
    return new PersonObj(name,ssn);
  }
  static public Person newPerson(String name, SSN ssn) {
    return new PersonObj(name,ssn);
  }
}

final class SSNObj implements SSN {
  final private String s;
  final private long l;
  SSNObj(String s) {
    this.s = s;
    this.l = Long.parseLong(s);
  }
  public String toString() { return s; }
  public long toLong() { return l; }
  // TODO: define equals, hashcode, compareTo
  public int compareTo(SSN that) { return -1; }
}

final class PersonObj implements Person {
  final private String name;
  final private SSN ssn;
  PersonObj(String name, SSN ssn) {
    if (null == name || 0 == name.trim().length())
      throw new IllegalArgumentException();
    this.name = name.trim();
    this.ssn = ssn;
  }
  PersonObj(String name, String ssn) {
    this(name,PersonFactory.newSSN(ssn));
  }
  public String name() { return name; }
  public SSN ssn() { return ssn; }
  // TODO: define equals, hashcode, compareTo
  public int compareTo(Person that) { return -1; }
}

file:factory/person/main/Main.java [source] [doc-public] [doc-private]
01
02
03
04
05
06
07
08
09
10
package factory.person.main;
import factory.person.Person;
import factory.person.PersonFactory;
public class Main {
  private Main() {}
  public static void main(String[] args) {
    Person p = PersonFactory.newPerson("Bob Jones","123456789");
    System.out.println(p);
  }
}

Previous pageContentsNext page