Pizza maker with Bloch builder I tried to implement the builder pattern of GoF. After searching for almost every related posts/examples on the Internet, I'm still confused. But I found that there are two kinds of patterns, which are both called builder:


Bloch Builder : A famous post, but a comment pointed out it's actually a fluent interface, still useful, though. Also notice that it's not the same as Method Chaining, see the differences.
Builder Pattern @thejavageek.com : The author gives a very clear structure of Builder Pattern: Director, Builder, ConcreteBuilder, Product.




Finally I decide to make my own version of "Builder Pattern", which follows the first link above, with some modifications:


The static method Pizza.makePizza() acts as the Director.
For simplicity, I didn't make the Factory a factory method or abstract factory, but it can be without problem.
Before you want to make a pizza, you have to override some methods, which you can put anything must be done before the pizza is created.




Main.java

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Factory myFactory = new Factory();

        Pizza myPizza = Pizza.makePizza(new Pizza.Builder(myFactory) {
            @Override
            public void prepareDough() {
                myFactory.prepareDough();
            }

            @Override
            public void prepareToppings() {
                myFactory.prepareToppings();
            }
        }.withSize(20).withBacon().withPepperoni());

        System.out.println(myPizza);
    }
}


Pizza.java

public class Pizza {
    private final int size;
    private final boolean cheese;
    private final boolean pepperoni;
    private final boolean bacon;

    private Pizza(Builder builder) {
        size = builder.size;
        cheese = builder.cheese;
        pepperoni = builder.pepperoni;
        bacon = builder.bacon;
    }

    public static Pizza makePizza(Builder builder) throws InterruptedException {
        builder.prepareDough();
        Thread.sleep(2000);
        builder.prepareToppings();
        Thread.sleep(2000);
        return new Pizza(builder);
    }

    public static abstract class Builder {
        private int size;
        private boolean cheese = false;
        private boolean pepperoni = false;
        private boolean bacon = false;

        public Builder(Factory factory) {
        }

        public Builder withSize(int size) {
            this.size = size;
            return this;
        }

        public Builder withCheese() {
            cheese = true;
            return this;
        }

        public Builder withPepperoni() {
            pepperoni = true;
            return this;
        }

        public Builder withBacon() {
            bacon = true;
            return this;
        }

        protected abstract void prepareDough();
        protected abstract void prepareToppings();
    }

    public String toString() {
        return String.format("pizza={size=%d, cheese=%s, pepperoni=%s, bacon=%s}",
            size,
            cheese,
            pepperoni,
            bacon);
    }
}


Factory.java

public class Factory {
    public Factory() {}

    public void prepareDough() {
        System.out.println("Preparing dough...");
    }

    public void prepareToppings() {
        System.out.println("Preparing toppings...");
    }
}


Result:

Preparing dough...
Preparing toppings...
pizza={size=20, cheese=false, pepperoni=true, bacon=true}
Your main() code feels cumbersome, and the modelling seems unnatural to me.  I also find that .withSize(20).withBacon().withPepperoni() is hard to read, perhaps due to its placement after the definition of the anonymous subclass of Pizza.Builder.


public class Main {
    public static void main(String[] args) throws InterruptedException {
        Factory myFactory = new Factory();

        Pizza myPizza = Pizza.makePizza(new Pizza.Builder(myFactory) {
            @Override
            public void prepareDough() {
                myFactory.prepareDough();
            }

            @Override
            public void prepareToppings() {
                myFactory.prepareToppings();
            }
        }.withSize(20).withBacon().withPepperoni());

        System.out.println(myPizza);
    }
}



Assuming that you are interested in constructing an immutable Pizza, I would prefer to see:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Pizza myPizza = new PizzaBase(20).addTopping(Pizza.Topping.BACON)
                                         .addTopping(Pizza.Topping.PEPPERONI)
                                         .bake();
        System.out.println(myPizza);
    }
}


In particular:


This interface mimics the process of making a pizza.
The base is mandatory, and you must specify its size.  The toppings are optional.
Offering an .addTopping(…) method that accepts a parameter is more flexible.  You might even be able to .addTopping(CHEESE) twice to get extra cheese.
I'm not convinced that dependency injection for the Factory is worthwhile.