Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clearing doubts about the builder pattern

I am learning about the builder pattern, and so far I understood that, it is a great alternative to the commonly patterns used for initialization:

  • Telescoping Constructor Pattern

  • JavaBean Pattern

The thing is, I don't really like to remove the getters and setters from the objects in my domain model. I always like to keep them as POJOs. One of the reasons I don't like it is: If i don't use POJOs, then it is not easy to annotate the variables when using ORM frameworks...

So here are my doubts: -Is it possible to implement the builder pattern without using static inner classes? -If I have to use the builder pattern by using the inner class, do you think it is correct to keep the getters and the setters? -I did a little example for practice where I tried to avoid the inner class. Could you let me what do you think about it?

Product

    public class Product
{
    private String color;
    private int price;

    public Product() {
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public String toString() {
        return getColor() + "\n" + getPrice();
    }    
}

Builder

public class Builder
{
    private Product product;

    public Builder() {
        product = new Product();
    }
    public Builder withColor(String color) {        
        product.setColor(color);
        return this;
    }

     public Builder withPrice(int price) {        
        product.setPrice(price);
        return this;
    }
    public Product build() {
        return product;
    }
}**

Client

public class Client
{

    public static void main(String[] args) {
        System.out.println(new Builder().withColor("Black").withPrice(11).build());
        System.out.println("-----------------------------------------------------");
        System.out.println(new Builder().withColor("Blue").withPrice(12).build());
    }
}

enter image description here

like image 276
javing Avatar asked Oct 17 '12 09:10

javing


People also ask

What problem does the builder pattern solve?

Builder pattern solves the issue with large number of optional parameters and inconsistent state by providing a way to build the object step-by-step and provide a method that will actually return the final Object.

What is the purpose of builder design pattern?

The builder pattern is a design pattern designed to provide a flexible solution to various object creation problems in object-oriented programming. The intent of the Builder design pattern is to separate the construction of a complex object from its representation.

What are the consequences of applying the builder design pattern?

Here are key consequences of the Builder pattern: It lets you vary a product's internal representation. The Builder object provides the director with an abstract interface for constructing the product. The interface lets the builder hide the representation and internal structure of the product.

What is the advantages of builder design pattern?

The main advantages of Builder Pattern are as follows: It provides clear separation between the construction and representation of an object. It provides better control over construction process. It supports to change the internal representation of objects.


3 Answers

The Builder pattern is useful to create immutable objects and avoid several constructors with optional parameters.

IMO using Builder pattern to build a POJO which can be updated using setters is useless. You only create an additional class.

Depending on the ORM framework used, it might not need the presence of setter method. But only assigning members values through reflection.

Product class:

public final class Product {
    private final String color;
    private final int price;

    public Product(Builder builder) {
        this.color = builder.getColor();
        this.price = builder.getPrice();
    }

    public String getColor() {
        return color;
    }

    public int getPrice() {
        return price;
    }

    public String toString() {
        return getColor() + "\n" + getPrice();
    }    
}

Builder class:

public final class Builder {

    private String color;
    private int price;

    public Builder() {
        // Assign any default values
    }

    public Builder color(String color) {        
        this.color = color;
        return this;
    }

    public Builder price(int price) {        
        this.price = price;
        return this;
    }

    protected String getColor() {
        return color;
    }

    protected int getPrice() {
        return price;
    }

    public Product build() {
        return new Product(this);
    }
}
like image 182
mkhelif Avatar answered Oct 30 '22 03:10

mkhelif


The builder pattern is most useful in the context of immutable objects. Immutable objects don't have setters by definition. So all of their properties have to be squeezed into the constructor. This is where the builder pattern comes in handy. It allows you to split the initialization of a complex immutable object into multiple, self-explaining instructions so you don't need to have constructor calls like this fictional example all over you code where you can't tell which argument does what:

Thing foo = new Thing(1, 125, Thing.SOMETHING, new Whatchamacallit(17, 676), getStuffManager(StuffManager.ZOMG), true, false, false, maybe);

I don't find that the Builder pattern creates any signficant value when the created object is mutable. Everything you do through the builder can also be done with the created object directly.

Also, I think that your program above is not a textbook example of the builder pattern. You usually don't create an object by passing the builder to the constructor. You create an object by calling a create method on the builder which then passes all its properties to the constructor of the object. This pattern has the advantage that it gives the builder the opportunity to check its internal state for consistency and maybe throw an exception before starting to build the object.

The java StringBuilder class is a good example (the create method being tostring in this case).

like image 22
Philipp Avatar answered Oct 30 '22 01:10

Philipp


What does using a builder here actually gain you?

Nothing as far as I can see: you could just create a new Product and use the getters and setters on it directly. If you have a simple POJO then there is absolutely nothing wrong with:

Product p=new Product();
p.setColour("Black");
p.setPrice(11);
doSomethingWith(p);

Saving a few characters of typing is IMHO not worth introducing a new class / builder abstraction.

Builders are more useful in situations like the following:

  • You want to create an immutable object (and hence can't use setters)
  • If you have complicated factory logic that cannot easily be expressed with simple getters and setters or that you want to re-use in different ways
  • (Occasionally) when you want to have different parts of the code base configure different aspects of the builder for some reason.
like image 33
mikera Avatar answered Oct 30 '22 03:10

mikera