up vote 3 down vote favorite

This question already has an answer here:

Recently I saw some of the developers coding their VOs with nested builder class like

public class User {

    private String firstName;
    private String lastName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public static class UserBuilder {

        private String firstName;
        private String lastName;

        public User build() {
            User user = new User();
            user.firstName = firstName;
            user.lastName = lastName;
            return user;
        }

        public UserBuilder withFirstName(String firstName) {
            this.firstName = firstName;
            return this;
        }

        public UserBuilder withLastName(String lastName) {
            this.firstName = firstName;
            return this;
        }       
    }

}

Now, they claim that this makes code more readable. My point is, this has following disadvantages:

  1. I can't simply add fields and expect my IDE to complete code for me, as now I need to update this inner class too.

  2. Simple POJOs are carrying code which is not relevant for VO.

I am looking for any advice if I am missing something here. Feel free to add your thoughts about the same.

Sample code after this modification looks like,

User user = new User.UserBuilder()
                .withFirstName("Name")
                .withLastName("surName")
                .build();
java design-patterns pojo share | improve this question edited Feb 9 '16 at 9:17 shmosel 18.9k 2 14 52 asked Feb 9 '16 at 9:06 techtrainer 191 3 12

marked as duplicate by Jarrod Roberson java Users with the  java badge can single-handedly close java questions as duplicates and reopen them as needed. Feb 10 '16 at 11:14

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

1   You usually use builders when you have many different possibilities for your constructor and many of them are of the same type. Thus, a builder makes everything more readable and reusable. –  LordAnomander Feb 9 '16 at 9:09 9   Builders avoid the "telescoping constructor" antipattern, wherein you end up with a combinatorial explosion of all of the possible optional constructor parameters. There is a detailed discussion in Effective Java 2nd Ed Item 2. –  Andy Turner Feb 9 '16 at 9:11 2   stackoverflow.com/questions/328496/… This link provides all the information you should know about the usage of the builder pattern. –  LordAnomander Feb 9 '16 at 9:17 6   I think builders are most useful for constructing immutable objects, where you would otherwise have to pass all the arguments into a constructor. The builder pattern makes construction more readable and flexible. But in your example User is mutable, so there's no much you can do with the builder that you can't do with the setters. –  shmosel Feb 9 '16 at 9:19 1   Josh bloch explains the use case - informit.com/articles/article.aspx?p=1216151&seqNum=2 –  XOXO Feb 9 '16 at 9:27  |  show 6 more comments

3 Answers 3

active oldest votes up vote 1 down vote

Here is an article from Joshua Bloch. He explains very well why, when and how to use a builder : http://www.informit.com/articles/article.aspx?p=1216151&seqNum=2

It is one of items in his book called Effective Java. I strongly advise you to read this book if you have a little experience with Java.

Main point :

When you you get a class with a lot of attribute there is several ways create an object and init it.

If you set one by one every attributes it can be wordy and your object could be altered after its creation. With this method it is impossible to make your class immutable and you cannot be sure that your object is in consistent state.

Exemple from the article :

public class NutritionFacts {
    // Parameters initialized to default values (if any)
    private int servingSize  = -1; // Required; no default value
    private int servings     = -1;  //     "     "      "      "
    private int calories     = 0;
    private int fat          = 0;
    private int sodium       = 0;
    private int carbohydrate = 0;

    public NutritionFacts() { }
    // Setters
    public void setServingSize(int val)  { servingSize = val; }
    public void setServings(int val)     { servings = val; }
    public void setCalories(int val)     { calories = val; }
    public void setFat(int val)          { fat = val; }
    public void setSodium(int val)       { sodium = val; }
    public void setCarbohydrate(int val) { carbohydrate = val; }
}

You can use a telescoping constructor. It can make your object immutable. However if you get many attributes it can be hard to write and read your code. More over when you just want create with one setted attribute, and unfortunately this one is the last parameter of the constructor, you have to set all parameter anyway.

Exemple from the article :

public class NutritionFacts {
    private final int servingSize;  // (mL)            required
    private final int servings;     // (per container) required
    private final int calories;     //                 optional
    private final int fat;          // (g)             optional
    private final int sodium;       // (mg)            optional
    private final int carbohydrate; // (g)             optional

    public NutritionFacts(int servingSize, int servings) {
        this(servingSize, servings, 0);
    }

    public NutritionFacts(int servingSize, int servings,
            int calories) {
        this(servingSize, servings, calories, 0);
    }

    public NutritionFacts(int servingSize, int servings,
            int calories, int fat) {
        this(servingSize, servings, calories, fat, 0);
    }

    public NutritionFacts(int servingSize, int servings,
            int calories, int fat, int sodium) {
        this(servingSize, servings, calories, fat, sodium, 0);
    }

    public NutritionFacts(int servingSize, int servings,
           int calories, int fat, int sodium, int carbohydrate) {
        this.servingSize  = servingSize;
        this.servings     = servings;
        this.calories     = calories;
        this.fat          = fat;
        this.sodium       = sodium;
        this.carbohydrate = carbohydrate;
    }
}

The builder allows to make your code more readable and easy to write. It also allows you to be able to make your class immutable.

Exemple from the article :

public class NutritionFacts {
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;

    public static class Builder {
        // Required parameters
        private final int servingSize;
        private final int servings;

        // Optional parameters - initialized to default values
        private int calories      = 0;
        private int fat           = 0;
        private int carbohydrate  = 0;
        private int sodium        = 0;

        public Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings    = servings;
        }

        public Builder calories(int val)
            { calories = val;      return this; }
        public Builder fat(int val)
            { fat = val;           return this; }
        public Builder carbohydrate(int val)
            { carbohydrate = val;  return this; }
        public Builder sodium(int val)
            { sodium = val;        return this; }

        public NutritionFacts build() {
            return new NutritionFacts(this);
        }
    }

    private NutritionFacts(Builder builder) {
        servingSize  = builder.servingSize;
        servings     = builder.servings;
        calories     = builder.calories;
        fat          = builder.fat;
        sodium       = builder.sodium;
        carbohydrate = builder.carbohydrate;
    }
}

In your example I'm not sure that it is very useful to do a builder for a class with only two attributes.

I hope this will help you.

share | improve this answer edited Feb 10 '16 at 10:51 answered Feb 9 '16 at 11:21 Thomas Betous 752 5 26      Please add at least the most important points to your answer. –  Markus Kull Feb 9 '16 at 11:25      It's done, I hope it is ok. –  Thomas Betous Feb 9 '16 at 11:48 add a comment  |  up vote 0 down vote

IMHO in the given example you gain no value by using Builder pattern. You can create User object without the Builder (because of all the setters). The only thing that Builder gives you in this particular case is Fluent Interface.

You should use Builder Pattern when there are various combinations of creating a valid object. Thanks to this you won't have to implement many constructors or factory methods.

Builder is also helpful when creating a valid object requires many parameters.

Builder should be responsible for build only a valid objects. In your case, if User needs to have first and last name Builder shouldn't allow to create the instance of User that doesn't have those attributes set.

share | improve this answer answered Feb 9 '16 at 20:49 Sebastian Malaca 101 1 6 add a comment  |  up vote 0 down vote

Start with small immutable objects

If all your properties are required then you should use just constructor. By doing this you might create nice small immutable object.

Builders are helpful when you have multiple optional fields

If there are multiple optional fields and different ways to create an object you'd need multiple constructors.

public User (int requiredParameter) { ... }
public User (int reqiredParameter, int optionalParameter) { ... }
public User (int reqiredParameter, int optionalParameter, String optionalParameter2) { ... }
public User (int reqiredParameter, String optionalParameter2) { ... }

It creates messy code. It is hard to determine which constructor you should use. In this case you could use nested builder to have intuitive way of creating your object.

share | improve this answer answered Feb 10 '16 at 9:20 Marcin Szymczak 4,384 2 18 38 add a comment  | 

Not the answer you're looking for? Browse other questions tagged java design-patterns pojo or ask your own question.

快照源:http://liqunsheng.blog.51cto.com/6703913/1691913