preload
Dez 02

Imagine you would like to create a payment in banking domain and you have to create an instance with many parameters. The first two parameters are mandatory and the others are optional. You would normally create it like:

1
Payment credit = new Payment(Payment.CREDIT, "1000", "Beneficiary account", "Beneficiary bank name", "Remitter account name", "Remitter bank name" );

This could be a long line, depending on the number of parameters. Also from the code you don’t know which parameter you actually set in the constructor. Ok, lets use Java Beans style with getter and setters:

1
2
3
4
5
6
7
Payment credit = new Payment();
credit.setType(Payment.CREDIT);
credit.setAmount(1000);
credit.setBeneficiaryAccountName("Beneficiary account name");
credit.setBeneficiaryAccountBankName("Beneficiary bank name");
credit.setRemitterAccountName("Remitter account name");
credit.setRemitterAccountBankName("Remitter bank name");

So far so good, now we know exactly what we set and we use Java Beans spec. But now we have the problem that the creation process is split between multiple calls of the setters. This could lead to an inconsistent state during the creation process. If somewhere between these setter calls a problem occurs, the objects could be initialized incompletely.

What if you could create an instance like the following:

1
2
3
4
5
6
Payment credit = Payment.Builder(Payment.CREDIT, 1000)
                        .beneficiaryName("Beneficiary name")
                        .beneficiaryAccount("Beneficiary account name")
                        .remitterName("Remitter name")
                        .remitterAccount("Remitter account name")
                        .build();

We seperated the optional from the mandatory parameters and improved readability. Also this is only one call and so is the instance in a consistent state.

Here is the example code of the class Payment:

1
2
3
4
5
6
7
8
9
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
public class Payment {
   private final static int CREDIT = 0;
   private final static int DEBIT = 1;
   private final int type; // required
   private final double amount; // required
   private final String beneficiaryAccount; // required
   private final String beneficiaryName; // required
   private final String remitterName; // optional
   private final String remitterAccount; // optional
 
 
   public static class Builder {
     // Required parameters
     private final int type;
     private final double amount;
     // Optional parameters - initialized to default values
     private String beneficiaryAccount = "";
     private String beneficiaryName = "";
     private String remitterName = "";
     private String remitterAccount = "";
 
     public Builder(int type, double amount) {
       this.type = type;
       this.amount = amount;
     }
 
     public Builder beneficiaryAccount (String val) { remitterAccount = val; return this; }
     public Builder beneficiaryName (String val) { remitterAccount = val; return this; }
     public Builder remitterName (String val) { remitterAccount = val; return this; }
     public Builder remitterAccount (String val) { remitterAccount = val; return this; }
     public Payment build() { return new Payment(this); }
   }
 
   private Payment(Builder builder) {
     type = builder.type;
     amount = builder.amount;
     beneficiaryAccount = builder.beneficiaryAccount;
     beneficiaryName = builder.beneficiaryName;
     remitterName = builder.remitterName;
     remitterAccount = builder.remitterAccount;
   }
}

Examples modified from the Book “Effective Java” http://www.amazon.de/gp/product/0321356683

Another great article can you find here: http://www.javablog.ch/2008/08/23/effective-java-builder-pattern/

Tagged with: