Builder Design Pattern

A class can be accessed by its objects or instance only, which requires a Constructor to create it where values will be passed. a Constructor can be either No Argument or Default Constructor, some Required Argument Constructor, or All Arguments Constructor.
but Constructors have Fixed Positional Parameters, either value should be passed with a specific order or null to fill the position. or a New Constructor must be created with the required values, with the addition of a new attribute, another Constructor would be required. this is also called Telescoping Constructors Problem.
Builder Design Pattern helps to solve this issue, instead of passing values into the Constructor, the Builder Design Pattern provides specific methods to set the value and a build method to combine all the passed values to create an object. it minimizes the requirement of passing non-required parameters and increases readability.

The Builder Pattern is used to construct a complex object with a step-by-step build process.

since the Builder Pattern doesn't provide setters so it makes the object immutable up to some extent.

package org.wesome.design.patterns;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Getter
@ToString
public class Apple {
    private final String name;
    private final String taste;

    Apple(String name, String taste) {
        this.name = name;
        this.taste = taste;
    }

    public static AppleBuilder builder() {
        return new AppleBuilder();
    }

    @NoArgsConstructor
    public static class AppleBuilder {
        private String name;
        private String taste;

        public AppleBuilder name(String name) {
            this.name = name;
            return this;
        }

        public AppleBuilder taste(String taste) {
            this.taste = taste;
            return this;
        }

        public Apple build() {
            return new Apple(name, taste);
        }

        public Apple.AppleBuilder copy(Apple o) {
            Apple.AppleBuilder copiedBuilder = this.name(o.getName()).taste(o.getTaste());
            return copiedBuilder;
        }
    }
}
package org.wesome.design.patterns;

public class Builder {
    public static void main(String[] args) {
        Apple macintosh = Apple.builder().build();
        System.out.println("macintosh " + macintosh);

        Apple macintoshCopy = Apple.builder().copy(macintosh).build();
        System.out.println("macintoshCopy " + macintoshCopy);

        Apple fuji = Apple.builder().name("Fuji").build();
        System.out.println("fuji = " + fuji);
        Apple fujiCopy = Apple.builder().copy(fuji).name("Fuji").build();
        System.out.println("fujiCopy = " + fujiCopy);

        Apple gala = Apple.builder().name("Gala").taste("sour").build();
        System.out.println("gala = " + gala);
        Apple galaCopy = Apple.builder().copy(gala).name("Gala").taste("sour").build();
        System.out.println("galaCopy = " + galaCopy);
    }
}
package org.wesome.design.patterns;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class BuilderTest {
    @Test
    void testBuilderWithAllNullParameters() {
        Apple macintosh = Apple.builder().build();
        Assertions.assertAll(() -> {
            Assertions.assertNotNull(macintosh);
            Assertions.assertNull(macintosh.getName());
            Assertions.assertNull(macintosh.getTaste());
        });
    }

    @Test
    void testBuilderWithSomeNullParameters() {
        Apple fuji = Apple.builder().name("Fuji").build();
        Assertions.assertAll(() -> {
            Assertions.assertNotNull(fuji);
            Assertions.assertNotNull(fuji.getName());
            Assertions.assertNull(fuji.getTaste());
        });
    }

    @Test
    void testApple() {
        Apple gala = Apple.builder().name("Gala").taste("sour").build();
        Assertions.assertAll(() -> {
            Assertions.assertNotNull(gala);
            Assertions.assertNotNull(gala.getName());
            Assertions.assertNotNull(gala.getTaste());
        });
    }
}
plugins {
    id 'java'
    id "io.freefair.lombok" version "6.2.0"
}

group = 'org.wesome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
}

test {
    useJUnitPlatform()
}

Builder Design Pattern increases the lines of code and each class needs to define another static build class.

follow us on