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());
}
}
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.
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.
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.
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.
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);
}
}
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).
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:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With