Skip to main content
3 of 10
edited tags
200_success
  • 144.2k
  • 22
  • 188
  • 473

Pizza builder with builder/template/factory pattern

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:

  • Fluent Interface : 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}
RainningTW
  • 531
  • 4
  • 14