Consider a situation where
- A Consuructor has too many arguments.
- We need to solve incorrect object state.
BankAccount account = new BankAccount(4456L, "Huston", "South Avenue", 100, 6);
BankAccount anotherAccount = new BankAccount(876L, "San Francisco", null, 6, 100);
Builder comes as a savior... Here is how?
public class BankAccount {
public static class Builder {
private long accountNumber; //This is important, so we'll pass it to the constructor.
private String owner;
private String branch;
private double balance;
private double interestRate;
public Builder(long accountNumber) {
this.accountNumber = accountNumber;
}
public Builder withOwner(String owner){
this.owner = owner;
return this; //By returning the builder each time, we can create a fluent interface.
}
public Builder atBranch(String branch){
this.branch = branch;
return this;
}
public Builder openingBalance(double balance){
this.balance = balance;
return this;
}
public Builder atRate(double interestRate){
this.interestRate = interestRate;
return this;
}
public BankAccount build(){
//Here we create the actual bank account object, which is always in a fully initialised state when it's returned.
BankAccount account = new BankAccount(); //Since the builder is in the BankAccount class, we can invoke its private constructor.
account.accountNumber = this.accountNumber;
account.owner = this.owner;
account.branch = this.branch;
account.balance = this.balance;
account.interestRate = this.interestRate;
return account;
}
}
private BankAccount() {
//Constructor is now private.
}
}
//Client
BankAccount account = new BankAccount.Builder(1234L)
.withOwner("Marge")
.atBranch("Springfield")
.openingBalance(100)
.atRate(2.5)
.build();
- A Consuructor has too many arguments.
- We need to solve incorrect object state.
BankAccount account = new BankAccount(4456L, "Huston", "South Avenue", 100, 6);
BankAccount anotherAccount = new BankAccount(876L, "San Francisco", null, 6, 100);
Builder comes as a savior... Here is how?
public class BankAccount {
public static class Builder {
private long accountNumber; //This is important, so we'll pass it to the constructor.
private String owner;
private String branch;
private double balance;
private double interestRate;
public Builder(long accountNumber) {
this.accountNumber = accountNumber;
}
public Builder withOwner(String owner){
this.owner = owner;
return this; //By returning the builder each time, we can create a fluent interface.
}
public Builder atBranch(String branch){
this.branch = branch;
return this;
}
public Builder openingBalance(double balance){
this.balance = balance;
return this;
}
public Builder atRate(double interestRate){
this.interestRate = interestRate;
return this;
}
public BankAccount build(){
//Here we create the actual bank account object, which is always in a fully initialised state when it's returned.
BankAccount account = new BankAccount(); //Since the builder is in the BankAccount class, we can invoke its private constructor.
account.accountNumber = this.accountNumber;
account.owner = this.owner;
account.branch = this.branch;
account.balance = this.balance;
account.interestRate = this.interestRate;
return account;
}
}
private BankAccount() {
//Constructor is now private.
}
}
//Client
BankAccount account = new BankAccount.Builder(1234L)
.withOwner("Marge")
.atBranch("Springfield")
.openingBalance(100)
.atRate(2.5)
.build();