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][1] : 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][2].

 * [Builder Pattern @thejavageek.com][3] : 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}


  [1]: https://stackoverflow.com/a/1953567/5290519
  [2]: https://stackoverflow.com/q/17937755/5290519
  [3]: http://www.thejavageek.com/2016/08/25/builder-design-pattern/