Java Builder Pattern Simple example

๐Ÿงฑ Builder Design Pattern in Java — Step-by-Step with Example

The Builder Pattern is a creational design pattern that provides a flexible solution for constructing complex objects step by step.
It’s especially useful when a class has many fields, and not all of them are required (some are optional).

Instead of passing dozens of constructor arguments (and remembering their order),
the Builder Pattern allows clean, readable object creation like this ๐Ÿ‘‡

Customer customer = new Customer.CustomerBuilder("Vinod", "Kumaran") .setCity("Bangalore") .setAddress("Electronic City") .build();

๐ŸŽฏ Why Builder Pattern?

Imagine you have a class with:

  • Mandatory fields (must always be provided)

  • Optional fields (can be skipped or defaulted to null)

If you use normal constructors, you might end up with “constructor telescoping”, like:

new Customer("Vinod", "Kumaran", null, "Bangalore", null);

This is hard to read, hard to maintain, and error-prone.

The Builder Pattern fixes this problem by providing:
✅ Better readability
✅ Clear separation of mandatory & optional fields
✅ Immutable objects
✅ Easy object construction


⚙️ Example Use Case

We’ll create a Customer class where:

  • firstName and lastName are mandatory

  • address, city, and zipCode are optional


๐Ÿงฉ Step 1: Create the Customer Class

package com.vinod.patterns; /** * Builder pattern example demonstrating how to create objects * with mandatory and optional parameters. */ public class Customer { // Mandatory fields private final String firstName; private final String lastName; // Optional fields private final String address; private final String city; private final String zipCode; // Private constructor to enforce the use of Builder private Customer(CustomerBuilder builder) { this.firstName = builder.firstName; this.lastName = builder.lastName; this.address = builder.address; this.city = builder.city; this.zipCode = builder.zipCode; } // Getters public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public String getAddress() { return address; } public String getCity() { return city; } public String getZipCode() { return zipCode; } @Override public String toString() { return "Customer [firstName=" + firstName + ", lastName=" + lastName + ", address=" + address + ", city=" + city + ", zipCode=" + zipCode + "]"; } /** * Static nested Builder class * Provides fluent methods to set optional parameters. */ public static class CustomerBuilder { // Required fields private final String firstName; private final String lastName; // Optional fields (initialized to null by default) private String address; private String city; private String zipCode; // Constructor with mandatory parameters public CustomerBuilder(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } // Setter methods for optional fields public CustomerBuilder setAddress(String address) { this.address = address; return this; } public CustomerBuilder setCity(String city) { this.city = city; return this; } public CustomerBuilder setZipCode(String zipCode) { this.zipCode = zipCode; return this; } // Build method to return final Customer object public Customer build() { return new Customer(this); } } }

๐Ÿงช Step 2: Test the Builder Pattern

package com.vinod.patterns; public class TestBuilderPattern { public static void main(String[] args) { // Case 1: Create Customer with only mandatory fields Customer customer1 = new Customer.CustomerBuilder("Vinod", "Kumaran") .build(); System.out.println(customer1); // Case 2: Create Customer with some optional fields Customer customer2 = new Customer.CustomerBuilder("Vinod", "Kumaran") .setAddress("Electronic City") .setCity("Bangalore") .build(); System.out.println(customer2); } }

๐Ÿงพ Output

Customer [firstName=Vinod, lastName=Kumaran, address=null, city=null, zipCode=null] Customer [firstName=Vinod, lastName=Kumaran, address=Electronic City, city=Bangalore, zipCode=null]

๐Ÿง  How It Works — Step by Step

StepActionExplanation
1️⃣Create a CustomerBuilderPass only mandatory fields to its constructor.
2️⃣Chain setter methodsUse fluent syntax to set optional fields.
3️⃣Call build()Constructs a Customer by passing builder data to the private constructor.
4️⃣Customer object is immutableBecause all fields are final and no setters exist in Customer.

๐Ÿงญ When to Use the Builder Pattern

ScenarioWhy Builder Helps
Many parameters (some optional)Avoids telescoping constructors
Object should be immutableBuilder handles initialization only once
Want readable, step-by-step object creationMethod chaining improves clarity
Need validation or defaultsAdd checks inside build()

⚡ Advantages

  • ✅ Clean and readable object creation

  • ✅ Avoids null handling for optional parameters

  • ✅ Supports immutability

  • ✅ Easy to extend without breaking existing code

  • ✅ Works perfectly in Java 8 and above


๐Ÿ” Summary

ConceptDescription
Pattern TypeCreational
Main IdeaSeparate object construction from representation
UsageWhen a class has multiple optional fields
ResultCleaner, safer, and more maintainable code

๐Ÿ’ฌ Real-World Analogy

Think of a pizza order ๐Ÿ• —
You must choose the base (mandatory), but toppings like cheese, olives, or mushrooms are optional.
The Builder Pattern lets you create the exact “pizza” you want, without forcing you to specify every topping each time.




No comments:

Post a Comment

Model Context Protocol (MCP) — Complete Guide for Backend Engineers

  Model Context Protocol (MCP) — Complete Guide for Backend Engineers Build Tools, Resources, and AI-Driven Services Using LangChain Moder...

Featured Posts