DEV Community

Cover image for Advance Builder Design Pattern — Java
Kareem Radwan
Kareem Radwan

Posted on

Advance Builder Design Pattern — Java

Introduction:

Each design pattern comes to solve a well known problem.
Builder Design Patter the Problem is :
There is a class that has a lot of variables inside the builder. Suppose we have a Student class and it has a constructor that contains 10 variables of different types. When one of the team members wants to create an object of the class, he will face some difficulties due to a large number of variables.

So the Builder Design Pattern was developed to solve this problem by providing a method that does not contain variables and uses the other setter to fill in the necessary parameters for the constructor.

Simple Example :

We want to apply the Builder Design Pattern to the example of Student.

public class Student {

private int id;
private String name;
private String major;
private String mobileNumber;
private double salary;

// Optional Private Constructor
pu Student(int id, String name, String major, String mobileNumber) {
    this.id = id;
    this.name = name;
    this.major = major;
    this.mobileNumber = mobileNumber;
}


public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getName() {
    return name;
}

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

public String getMajor() {
    return major;
}

public void setMajor(String major) {
    this.major = major;
}

public String getMobileNumber() {
    return mobileNumber;
}

public void setMobileNumber(String mobileNumber) {
    this.mobileNumber = mobileNumber;
}

public double getSalary() {
    return salary;
}

public void setSalary(double salary) {
    this.salary = salary;
}

}

To Apply Builder Design Patter we need a New Class to Collect Data Variables and after the user fills all parameter data we Create Object from Student Class so we need to Declare ‘SimpleStudentBuilder’ class.

Notes :

  • We need to Declare this class ‘SimpleStudentBuilder’ inner in Student Class because we need to change Student Constructor to private and an inner class, we can init the new object form Student.

  • We Need also Declare ‘SimpleStudentBuilder’ Static because we can use it from outer class and not init object from student :)

SimpleStudentBuilder Class:

// This Class inner in Student class

public static class SimpleStudentBuilder {

private int id;
private String name;
private String major;
private String mobileNumber;
private double salary;


public SimpleStudentBuilder() {
}

public SimpleStudentBuilder setId(int id) {
    this.id = id;
    return this;
}

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

public SimpleStudentBuilder setMajor(String major) {
    this.major = major;
    return this;
}

public SimpleStudentBuilder setMobileNumber(String mobileNumber)     {
    this.mobileNumber = mobileNumber;
    return this;
}

public SimpleStudentBuilder setSalary(double salary) {
    this.salary = salary;
    return this;
}

public Student build() {
    // TODO : Check All Require Parameters is not null
    if (id == 0)
        throw new NullPointerException("Id Can't be with out value");

    if (name == null)
        throw new NullPointerException("Name Can't be Null");

    if (major == null)
        throw new NullPointerException("Major Can't be Null");

    if (mobileNumber == null)
        throw new NullPointerException("Number Can't be Null");

    Student student = new Student(id, name, major, mobileNumber);
    student.salary = salary;

    return student;
}

}

you can show full code in the GitHub repository.

Usage SimpleStudentBuilder :

public static void main(String[] args) {

Student student = new Student.SimpleStudentBuilder()
        .setMajor("IT")
        .setName("Kareem Radwa")
        .setMobileNumber("0597190510")
        .setSalary(1000)
        .setId(32)
        .build();

}

Deep In Builder Design Patter :)

Suppose in Student Constructor we have priority in passing parameter values for example in order [ id, name, major, mobile number ] If this arrangement disappears you will not be able to create an Object from Class Student.

so we need to answer to this situation the answer is Step Builder, but how we can implement this answer. keep reading :)

Step Builder Design Patter :

To apply this idea you need

A number of interfaces with the same number of Require variables so in Our example Student class we need 4 interfaces and in addition, we need one more interface for Build Method and optional variables.
Class is implemented all the above interfaces we need captions this ‘Steps’

The explanation for Usage StudentStepBuilder:

When we need to use this approach of builder you need to show in first time only id set method and if the user fil it, you can after that set Name variable value, etc.

Time Of coding:

public class StudentStepBuilder {

public static IdFiled newBuilder() {

    return new Steps();

}


public static interface IdFiled {
    NameFiled setId(int id);
}

public static interface NameFiled {

    MajorFiled setNmae(String name);

}

public static interface MajorFiled {

    MobileNumber setMajor(String major);

}

public static interface MobileNumber {

    BuildStep setMobile(String mobile);

}


public static interface BuildStep {

    BuildStep setSalary(double salary);

    Student build();
}

private static class Steps implements IdFiled, NameFiled, MajorFiled, MobileNumber, BuildStep {

    private int id;

    private String name;

    private String major;

    private String mobileNumber;

    private double salary;


    @Override
    public NameFiled setId(int id) {
        this.id = id;
        return this;
    }

    @Override
    public MajorFiled setNmae(String name) {
        this.name = name;
        return this;
    }

    @Override
    public MobileNumber setMajor(String major) {
        this.major = major;
        return this;
    }

    @Override
    public BuildStep setSalary(double salary) {
        this.salary = salary;
        return this;
    }

    @Override
    public BuildStep setMobile(String mobile) {
        this.mobileNumber = mobile;
        return this;
    }

    @Override
    public Student build() {
        if (id == 0) {
            throw new NullPointerException("ID Can't be 0");
        }
        if (name == null) {
            throw new NullPointerException("Name can't be null");
        }


        if (major == null) {
            throw new NullPointerException("Major can't be null");
        }

        if (mobileNumber == null) {
            throw new NullPointerException("Mbile Number can't be null");
        }

        Student student = new Student(id, name, major, mobileNumber);
        student.setSalary(salary);

        return student;
    }


}

}

Usage StudentStepBuilder:

Result of Step Builder Design Pattern
all code in GitHub repository: link

Finally

This is the First Article for me. I wish happy when you reading it.

Medium:

Top comments (12)

Collapse
 
luccabiagi profile image
Lucca Biagi

As an Study topic is really, really good! I really wish that when I was studying, I would have been able to read this...

Well, as @frmaglia sugested, on work you can use the Immutables lib or the polemic Project Lombok, we use it at the company that I work and it really saves development time.

Anyway, good article! Congratulations!

Collapse
 
kareemradwan profile image
Kareem Radwan

thank you very much for this reply.

I am thinking of writing a detailed article for every design pattern in advanced

Collapse
 
siy profile image
Sergiy Yevtushenko

Good article. Sad that Builder itself is anti-pattern in most cases, including one used by you in examples. dev.to/siy/when-builder-is-anti-pa...

Collapse
 
kareemradwan profile image
Kareem Radwan

Hi Sergiy, I am very happy for your reply.

But in the Builder Design Pattern:
1- The constructor can't must be private . so you can still constructor public and any developer use it and fill all require parameters.

2- I agree with you to the extent that error in compile time is better than an error in Run Time.
But in the case of my article, look at the last example. The developer cannot see the setMajor method except if it calls the setName method for example.
I think we can overcome the problem of forgetting some data without entering.

Collapse
 
siy profile image
Sergiy Yevtushenko
  1. This will result to inconsistent instance creation and increase coupling in places where 'new' is used to create instance.
  2. This is another pattern called "fluent interface". It works fine and solves all Builder issues. Unfortunately implementation involves a lot of boilerplate and does not make sense as general approach for POJO creation.
Thread Thread
 
kareemradwan profile image
Kareem Radwan

1- Yes, but this is written in Design patterns constructor can be optional private as I remember.

2- for point two you can use Immutables lib (immutables.github.io/immutable.html) and have it for free as some readers mention above. :).

Thank you very much, Mr Sergiy

Thread Thread
 
siy profile image
Sergiy Yevtushenko
  1. Design patterns are not a Holy Bible and always should be taken with grain of salt. Exposing constructor while having Builder or Factory/Factory method is a bad practice, as I've mentioned above.
  2. Yeah, tooling may help a lot to solve such problems.
Thread Thread
 
kareemradwan profile image
Kareem Radwan

Yes, I agree with you,
But I explain how Builder and Step Builder work.

thank you.

Collapse
 
frmaglia profile image
Francesco Maglia

You can avoid the hassle of doing it manually by using Immutables lib (immutables.github.io/immutable.html) and have it for free.

Collapse
 
orenovadia profile image
orenovadia

Does Intellij work well with this library?

Autocompletes, go to definition, etc...

Collapse
 
kareemradwan profile image
Kareem Radwan

oh, thank you very very much.

But in this article, I explain it to other students because I'm a student and I get this topic in university.

Collapse
 
proclus profile image
Ogla Sungutay

Hi Kareem, thanks for the article! It gave me inspiration for my Typescript project which uses inner classes.