Home > Mobile >  Builder pattern build() method output
Builder pattern build() method output

Time:10-25

After reading the Design Patterns book and looking at Builder pattern examples online, I have noticed that there are two different ways of returning the object in the final "build()" method. I was wondering what is the difference between:

Simply returning the maze we have been building

public class MazeBuilderImpl implements MazeBuilder {

private Maze maze;

@Override
public MazeBuilder builder() {
    maze = new Maze();
    return this;
}

// adding rooms, doors etc.

@Override
public Maze build() {
    return maze;
}
}

Passing the maze as a parameter in a constructor and returning that

public class MazeBuilderImpl implements MazeBuilder {

private Maze maze;

@Override
public MazeBuilder builder() {
    maze = new Maze();
    return this;
}

// adding rooms, doors etc.

@Override
public Maze build() {
    return new Maze(maze);
}
}

CodePudding user response:

First one seems worse. The original builder can subsequently be used to modify the state of the built object, since it still holds a reference to it.

MazeBuilder builder = new MazeBuilderImpl();
Maze maze = builder.rooms(1).build();
builder.rooms(2); // modifies the state of maze ...

The copy in the second one prevents that from happening, and allows the builder to be reused.

Both are bad though, since Maze is implied to be mutable. Builders are best for building immutable objects. It requires re-declaring the fields of Maze as fields of MazeBuilder, i.e. if Maze has a String id field, so will MazeBuilder. Lombok can help with reducing that boilerplate.

CodePudding user response:

If you return same object as in builder as follow:

@Override
public Maze build() {
    return maze;
}

then you will be referencing same object present in builder. And it can be still muted (changed). So your object could be still changes from somewhere. It still one object that you can affect directly or throuht builder.

If you return different object, you dont have to worry about builder affecting it after calling build().

But if your object can be immutable, then its common to have copy of objects fields in builder and construct object in build() method.

public class MazeBuilderImpl implements MazeBuilder {

    private Room roomA;
    private Room roomB;
    private Door doorA;
    private Door doorB;
    ....


    // adding rooms, doors etc.

    @Override
    public Maze build() {
        return new Maze(roomA, roomB, doorA, doorB, ...);
    }
}
  • Related