Java is the best way to implement a builder pattern

Which of the following is the best approach to implement the builder pattern?

1) Using an object for assembly instead of all its properties in the builder (and create it in the constructor constructor):

public class Person { private String firstName; // other properties ... private Person() {} // getters ... public static class Builder { // person object instead of all the person properties private Person person; public Builder() { person = new Person(); } public Builder setFirstName(String firstName) { person.firstName = firstName; return this; } // other setters ... public Person build() { if (null == person.firstName) { throw new IllegalStateException("Invalid data."); } return person; } } } 

2) Using the properties of the object for assembly instead of the object directly in the builder (and create it in the build () method):

 public class Person { private String firstName; // other properties ... private Person() {} // getters ... public static class Builder { // person properties instead of object private String firstName; // other properties ... public Builder() {} public Builder setFirstName(String firstName) { this.firstName = firstName; return this; } // other setters ... public Person build() { if (null == this.firstName) { throw new IllegalStateException("Invalid data."); } Person person = new Person(); person.firstName = firstName; return person; } } } 

I prefer the first method, because I think that with many properties, repeating them in the builder is redundant. Are there some flaws with the first approach?

Thanks in advance and sorry for my bad english.

+14
source share
3 answers

A little note. Yes, properties can be a repetition, but they have advantages.

Details below: If you look at the details here .

 Pizza pizza = new Pizza(12); pizza.setCheese(true); pizza.setPepperoni(true); pizza.setBacon(true); 

The problem is that since an object is created over several calls, it may be in an inconsistent state partly through its construction. It also requires a lot of effort to ensure thread safety.

A better alternative is to use the Builder template.

Please note that the method in Builder and the corresponding constructor or parent class of Pizza are the full code in the link here

  public static class Builder { public Pizza build() { // Notice this method return new Pizza(this); } } private Pizza(Builder builder) { // Notice this Constructor size = builder.size; cheese = builder.cheese; pepperoni = builder.pepperoni; bacon = builder.bacon; } 
+9
source

The Builder template is described in the Four Banks book, Sample Patterns, which states:

A design template is a design template that allows you to create complex objects in stages using the correct sequence of actions . The design is controlled by a director object, which should know only the type of object it should create.

If there is a sequence of steps that must be followed when building the object, then go to the second option.

In your first rule, the correct sequence of actions is not controlled. You can go for any option if the sequence of actions is not defined.

+2
source

I think that in your case there is no place where you can create an object. The builder will be used equally in both cases with a minimal difference in performance.

But if the object is immutable, and the field can be created by more than one step, I would certainly go with the second approach. For example, you can check the source code of java.lang.StringBuilder and see that the String object was created in the last step:

 public String toString() { // Create a copy, don't share the array return new String(value, 0, count); } 

In addition, I prefer the wizard template. This is an extension of the Builder pattern that protects you from receiving an IllegalStateException.

 public class Person { private String firstName; // other properties ... private Person() {} // getters ... public static class Builder { public Builder() {} public FirstStep setFirstName(String firstName) { return new FirstStep(firstName); } public static class FirstStep { private String firstName; private FirstStep(String firstName) { this.firstName = firstName; } public Person build() { Person person = new Person(); person.firstName = firstName; return person; } } } } 
+1
source

All Articles