Builder Programming Pattern

Introduction

The builder pattern provides a build object which is used to construct a complex object called the product.
It encapsulates the logic of constructing the different pieces of the product.

Definition

Builder is a creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.

Problem solved by „Builder”

Imagine a complex object that requires laborious, step-by-step initialization of many fields and nested objects. Such initialization code is usually buried inside a monstrous constructor with lots of parameters. Or even worse: scattered all over the client code.
 
In this example i will use  BankAccount class, which requires 3 arguments.
public class BankAccount {

    public String name;
    public String accountNumber;
    public String email;

    public BankAccount(String name, String accountNumber, String email)
    {
        this.name = name;
        this.accountNumber = accountNumber;
        this.email = accountNumber;
    }
}

Solution

BankAccount constructor is now marked as private, so that only the Builder assigned to this class can access it. Moreover it is taking Builder object as a parameter.

public class BankAccount {

    private String name;
    private String accountNumber;
    private String email;

    private BankAccount(BankAccountBuilder builder)
    {
        this.name = builder.name;
        this.accountNumber = builder.accountNumber;
        this.email = builder.accountNumber;
    }

    public static class BankAccountBuilder {

        private String name;
        private String accountNumber;
        private String email;

        public BankAccountBuilder(String name, String accountNumber) {
            this.name = name;
            this.accountNumber = accountNumber;
        }

        public BankAccountBuilder withEmail(String email) {
            this.email = email;
            return this;
        }

        public BankAccount build() {
            return new BankAccount(this);
        }
    }
}

Any mandatory fields are required as arguments to the inner class’s constructor, while the remaining optional fields can be specified using the setter methods.

BankAccount newAccount = new BankAccount
  .BankAccountBuilder("Jonathan", "12345678")
  .withEmail("Jonathan@example.com")
  .build();

It is necessary to call build method from Builder class, otherwise we will not get BackAccount object.

Pros

  • You can construct objects step-by-step, defer construction steps or run steps recursively.
  • You can reuse the same construction code when building various representations of products.
  • Single Responsibility Principle. You can isolate complex construction code from the business logic of the product.

Cons

  • The overall complexity of the code increases since the pattern requires creating multiple new classes.
Posted in Programming patternsTags:
Write a comment