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.




Java EE WebSocket Simple example

WebSocket is a protocol which allows for communication between the client and the server/endpoint using a single TCP connection. The advantage WebSocket has over HTTP is that the protocol is full-duplex (allows for simultaneous two-way communcation).

Here is one simple example to create a WebSocket endpoint and communicate it from a client.

Softwares Used

Java 1.7, Apache Tomcat, Eclipse

1. Create a Maven project with webapp archetype.

image

2.Create a WebSocket end point.

package com.pretech.test.websockets;
 
import java.io.IOException;
 
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
 
@ServerEndpoint("/websocket")
public class WebSocketTest {
 
    @OnMessage
    public void onMessage(String message, Session session) throws IOException,
            InterruptedException {
        System.out.println("User input: " + message);
        session.getBasicRemote().sendText("Hello world Mr. " + message);
        // Sending message to client each 1 second
        for (int i = 0; i <= 25; i++) {
            session.getBasicRemote().sendText(i + " Message from server");
            Thread.sleep(1000);
 
        }
    }
 
    @OnOpen
    public void onOpen() {
        System.out.println("Client connected");
    }
 
    @OnClose
    public void onClose() {
        System.out.println("Connection closed");
    }
}

@ServerEndpoint annotation is used at type level and defines the current class as a websocket server endpoint. The value used in this annotation represents the URL where the endpoint will be listening for client connections

3. Create an html page

<!DOCTYPE html>
<html>
<head>
<title>Pretech blog testing web sockets</title>
</head>
<body>
    <div>
        <input type="text" id="userinput" /> <br> <input type="submit"
           value="Send Message to Server" onclick="start()" />
    </div>
    <div id="messages"></div>
    <script type="text/javascript">
        var webSocket = new WebSocket(
                'ws://localhost:8080/pretech-websocket-example-1.0-SNAPSHOT/websocket');

        webSocket.onerror = function(event) {
            onError(event)
        };

        webSocket.onopen = function(event) {
            onOpen(event)
        };

        webSocket.onmessage = function(event) {
            onMessage(event)
        };

        function onMessage(event) {
            document.getElementById('messages').innerHTML += '<br />'
                    + event.data;
        }

        function onOpen(event) {
            document.getElementById('messages').innerHTML = 'Now Connection established';
        }

        function onError(event) {
            alert(event.data);
        }

        function start() {
            var text = document.getElementById("userinput").value;

            webSocket.send(text);
            return false;
        }
    </script>
</body>
</html>

4. Build and deploy the war

Build the maven project and deploy the war in to tomcat server. Once the server is started hit the blow url.

http://localhost:8080/pretech-websocket-example-1.0-SNAPSHOT/hello.html

We will see the connection established message in the screen, now enter your name and submit the request.

image

image

 

5. Download this example

 

Download WebSoket Example

 

Ref: Netbeans

Java Enum constructor example

Example

package com.vinod.test;

public class EnumConstructor {

    public static void main(String[] args) {
        // Getting year values
        System.out.println("Year " + Days.YEAR.getValue() + "   days");

        // Getting all values
        for (Days day : Days.values()) {
            System.out.println(day.getValue());

        }
    }

}
enum Days {
    YEAR(365), MONTH(30), WEEK(7);
    private int value;
    private Days(int value) {
        this.value = value;
    }
    public int getValue() {
        return value;
    }
}

Output

Year 365   days
365
30
7

Java ListIterator Example

The ListIterator interface is a special kind of iterator designed to iterate over lists. It provides functionality to iterates a list in both direction. Here is one example to iterate a list in reverse order using ListIterator.

Example

package mycollectiontest;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListIterator {

public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("One");
list.add("Two");
list.add("Three");
list.add("Four");
list.add("Five");
// Iterator allows only one direction
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());

}
// ListIterator allows traversing both direction
java.util.ListIterator<String> listIterator = list.listIterator(list.size());
while (listIterator.hasPrevious()) {
System.out.println(listIterator.previous());
}
}

}

Output

One
Two
Three
Four
Five
Five
Four
Three
Two
One

Java custom serialization example

Here is one example to see how to override the default Java serialization mechanism and how to do the implementation.
When we need to implement custom serialization we also have to define writeObject and/or readObject methods in our serializable class. Here we are not overriding these methods but JVM checks this methods.
Use case: I have an employee class and i do not want to serialize employees object in case employee address is null or zero length.

CustomSerializaion Example

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class CustomSerializaionExample {

    public static void main(String[] args) {
        Employee emp= new Employee("Vinod", "");

        FileOutputStream fos;
        try {
            // Serialization
            fos = new FileOutputStream(new File("employee.ser"));
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(emp);
            oos.flush();
            oos.close();

            // Deserialization
            FileInputStream fis = new FileInputStream("employee.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
            Employee deemp = (Employee) ois.readObject();
            ois.close();
            System.out.println("Customer after serialization: " + deemp);
        } catch (IOException | ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

class Employee implements Serializable {
    private static final long serialVersionUID = 5845255930677343859L;

    private String name;
    private String address;

    public Employee(String name, String address) {
        super();
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    private void writeObject(ObjectOutputStream o) throws IOException {

        if (address == null || address.length() == 0) {
            throw new IllegalArgumentException();

        }
        o.writeObject(name);
        o.writeObject(address);
    }

    private void readObject(ObjectInputStream o) throws IOException,
            ClassNotFoundException {

        name = (String) o.readObject();
        address = (String) o.readObject();
       
    }

    @Override
    public String toString() {
        return "Employee [name=" + name + ", address=" + address + "]";
    }

}

Output

Exception in thread "main" java.lang.IllegalArgumentException
at com.pretech.test.Employee.writeObject(CustomSerializaionExample.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1495)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
at com.pretech.test.CustomSerializaionExample.main(CustomSerializaionExample.java:21)

What is Robustness?

Robustness is the ability of software systems to react appropriately to abnormal conditions.

Ref: Object Oriented software Construction by Bertrand Meyer

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