To continue from the first part, let’s see how we can extend the functionality of an existing builder.

Basic Builder

Let’s take a simple builder for an example tha builds a NPC object:

public class NPC {

    private String name;

    private NPC(Builder builder) {
        this.name = builder.name;
    }

    public static class Builder {
        private String name;

        public Builder() {

        }

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

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

While counter-intuitive for such a simple use case, this will be our basic builder. Now, let’s see how we’ll extend on this!

Extends… or does it?

Let’s create a new class we want to build. This class will be called Guard and it’ll extend from NPC.

public class Guard extends NPC {
    private int strength;

    public Guard(Builder builder) {
        super(builder);

        // Hmm? How do we get this?
        this.strength = builder.strength;
    }
}

It almost works, but not quite. Our NPC.Builder does not have the strength field. Hmm… Maybe we should create a builder for Guard that extends from NPC.Builder?

public class Guard extends NPC {
    private int strength;

    public Guard(Builder builder) {
        super(builder);
        this.strength = builder.strength;
    }

    public static class Builder extends NPC.Builder {
        private int strength;

        public Builder() {

        }

        public Builder strength(int str) {
            this.strength = str;
            return this;
        }

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

Oooo-kay, seems to work. Let’s see the usage:

NPC npc = new NPC.Builder().name("Foo").build();
Guard guard = new Guard.Builder().strength(5).build();

Okay, this works too! Great! Let’s create another Guard:

Guard otherGuard = new Guard.Builder().strength(5).name("Thor").build();

Errr. This doesn’t work! If you tried this in your editor, you probably got and error saying “incompatible types”. What’s going on?

Types And Builders

The reason the last bit of code didn’t work is that when we called name() to set the guard’s name, we left the scope of the Guard.Builder and started working on the NPC.Builder, which has no idea that the Guard class even exists. Similarly, if you tried to set the name first, you wouldn’t be able to set the guard’s strength anymore - not that it matters at all since we can’t construct a guard anyway.

But wait! We can use generics to achieve what we wanted! For this, we have to create a new abstract builder which takes two type arguments: First type B denotes the type of the builder, and the second type T denotes the type of the object the builder creates. The abstract builder looks like this:

// B is the type of the builder, T is the type of the resulting object
public abstract static class AbstractBuilder<B, T> {
    // the build method returns an object of type T (the resulting object)
    public abstract T build();
}

Next, we make the NPC.Builder extend AbstractBuilder:

// The NPC builder takes a builder type that extends NPC.Builder, and a result
// type that extends NPC. In turn, the NPC builder passes itself as a builder type
// to the AbstractBuilder, and NPC as the result type.
public static class Builder<B extends NPC.Builder, T extends NPC> extends AbstractBuilder<NPC.Builder, NPC> {
    private String name;

    // NPC builder doesn't care what the builder type is, hence the resulting
    // type 'B'
    public B name(String name) {
        this.name = name;
        // We have to cast this builder "back" to type B first!
        return (B) this;
    }

    @Override
    public NPC build() {
        return new NPC(this);
    }
}

And finally, let’s make the Guard.Builder extend the NPC.Builder:

// Pass the Guard.Builder as the 'builder type', and Guard as the 'result' type
public static class Builder extends NPC.Builder<Guard.Builder, Guard> {
    private int strength;

    public Builder strength(int str) {
        this.strength = str;
        return this;
    }

    @Override
    public Guard build() {
        return new Guard(this);
    }
}

Great! Now we can use the builders just as we like:

// We can create ordinary NPCs
NPC npc = new NPC.Builder<>().build();

// And guards
Guard guard = new Guard.Builder().strength(5).build();

// We can set both NPC and Guard parameters...
Guard otherGuard = new Guard.Builder().strength(5).name("Thor").build();

// ... and the order doesn't matter!
Guard third = new Guard.Builder().name("Sven").strength(9).build();

Conclusion

By extending builders, we can create really complex builder hierarchies and many different types of resulting objects. The usage of the builders is still as easy as always - we just introduce new functionality by extending the old builders.