-1

Just getting my head around the Builder pattern and I have a few (noob) questions. Mainly, why can't we just simplify the creation of a builder object?

Instead of this:

public final class Foo {

    private final String name;
    private final String description;

    private Foo(String name, String description) {
        this.name = name;
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }

    public static class Builder {
        private String name;
        private String description;

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

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

        public Foo build() {
            return new Foo(name, description);
        }

    }

}

//Use it
Foo f = new Foo.Builder().setName("test").setDescription("description").build();

Why not just use this?

public final class Foo {

    private String name;
    private String description;

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    } 

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

    public Foo setDescription(String description){
       this.description=description;
       return this; 
    }
}

//Use it
Foo f = new Foo().setName("test").set("description");

I see maybe the first one is used when you want to build an immutable object, but other than that why can't I just use the second one instead? It's far simpler. Please provide examples as much as possible.

superigno
  • 994
  • 2
  • 12
  • 24

3 Answers3

1

The builder pattern is useful when there are operations that are valid during construction that are not valid once the object is built.

Yes, this is most obviously the case for building immutable objects, but it also applies very often when only some aspects of the object are immutable. Common examples are:

  • Often the identifier for an object (a person's name, for example) is specified during construction, but is not allowed to change after that;
  • Injected dependencies, like the database to use, the log to use, etc., are often not allowed to change after construction;
  • Factories and strategies are often not allowed to change after construction, because the object expects consistency across all their outputs.

Also, sometimes a setter on a valid object would have an effect, like dispatching an event, for example, that you don't want to happen during construction. You can sometimes get around that via complicated rules like "don't attach listeners until you're finished setting stuff up", but complicated rules are to be avoided.

Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87
1

Using your Second approach , i will be able to create a Object by doing.

Foo f = new Foo().setDescription("description");

Which means, We java created a object in your system without a name.
If we take another example which will be must self explanatory .

Employee emp = new Employee ().setDescription("manager");

Which means i hired a manager in a company without even know name.

Basically with Build() , we can also make sure all the required member variable are provided while creating a object. We can even do basic vaidation if needed.

public Foo build() {
                if(name == null){
                    throw Exception();
                else
                    return new Foo(name, description);
}
James
  • 161
  • 1
  • 6
  • What do you mean? I can also create an object without a name using this: Foo f = new Foo.Builder().setDescription("description").build(); – superigno May 04 '20 at 09:25
  • That's because your sample build method is not proper. It is not validating the must have fields. – James May 04 '20 at 09:53
  • If I add a build method on my second approach: Foo f = new Foo().setDescription("description").build() and put a validation there, then it would be the same thing. – superigno May 05 '20 at 01:21
0

Your way is "JavaBeans Patterns", From effectice java item2:"JavaBean Patterns" construction is split across multiple calls, a JavaBean may be in an inconsistent state partway through its construction. The class does not have the option of enforcing consistency merely by checking the validity of the constructor parameters. Attempting to use an object when it’s in an inconsistent state may cause failures that are far removed from the code containing the bug and hence difficult to debug. A related disadvantage is that the JavaBeans pattern precludes the possibility of making a class immutable and requires added effort on the part of the programmer to ensure thread safety. "Builder Pattern" is thread safe and more readable.

you can use lombok @Builder annotation to make a class "Builder Pattern".

LiLi
  • 391
  • 3
  • 11