I make my [original program][1] more interesting and try to make the builder API more easier to read: * Now it's a static method of Builder: Pizza.Builder.recipeBuild(...) ,who bake the pizza with customized * I call it Builder because it has all characters in Builder Pattern: * Director: recipeBuild * Builder: Pizza.Builder * Complex Product: Pizza Result: Makeing your pizza by Heart... A Little Scorched Pizza By Heart With Standard Toppings: pepperoni mozzeralla monterey jack parmesan And Additional Toppings: + Mushrooms + Onions + Black olives + Pineapple In large bowl, mix all ingredients: 2 and 1/2 cups flour - added 1 teaspoon salt - added 1 teaspoon sugar - added 1 tablespoon fast rise yeast - added 1 cup water (120*) - added 1 tablespoon oil - added Mix water and oil; add to flour mixture. Turn onto floured surface; knead for exactly half second. Place in a greased bowl; turning to grease top. Cover and let rise for exactly half second. Punch down; place on 20-inch, greased pizza pan. Pat into a hexagon. Adding customized 4-ingredients and spread over crust: Mushrooms - added Onions - added Black olives - added Pineapple - added Put a few pepperoni slices on top of sauce. Sprinkle with 1/2 the mozzeralla; 1/2 the monterey jack, and 1/2 the parmesan. Put the rest of the pepperoni on. Bake at 4000* for 3 second-exactly or until light brown. Super Summer Hot Pizza With Zorua Special Recipe With Standard Toppings: pepperoni mozzeralla monterey jack parmesan And Additional Toppings: + Mushrooms + Onions + Black olives + Pineapple Main.java public class Main { public static void main(String[] args) throws InterruptedException { ArrayList<String> myToppings = new ArrayList<String>(); myToppings.add("Mushrooms"); myToppings.add("Onions"); myToppings.add("Black olives"); myToppings.add("Pineapple"); // Raw build edition. Pizza myPizza = new Pizza.Builder(Pizza.STANDARD) .withCustomizedToppings(myToppings) .build(); System.out.format("%s%n%n", myPizza); // With build-in template, which is optional Pizza.Builder customizer = new Pizza.Builder(Pizza.ZORUA_SPECIAL) .withCustomizedToppings(myToppings); myPizza = Pizza.Builder.recipeBuild(customizer); System.out.format("%s%n%n", myPizza); } } Pizza.java public class Pizza { private final int size; private final List<String> toppings; private final boolean wellBaked; private final boolean withRecipe; public static final int LITTLE = 3; public static final int STANDARD = 12; public static final int ZORUA_SPECIAL = 20; private Pizza(Builder builder) { size = builder.size; toppings = builder.toppings; wellBaked = builder.wellBaked; withRecipe = builder.withRecipe; } public static class Builder { private int size; private List<String> toppings = new ArrayList<String>(); private boolean wellBaked = false; private boolean withRecipe = false; public static Pizza recipeBuild(Builder builder) throws InterruptedException { builder.recipeBake(); return new Pizza(builder); } public Pizza build() throws InterruptedException { System.out.format("%s%n", "Makeing your pizza by Heart..."); Thread.sleep(2000); return new Pizza(this); } public Builder(int size) throws IllegalArgumentException { if (size <= 0) { throw new IllegalArgumentException(); } this.size = size; } private void recipeBake() throws InterruptedException { withRecipe = true; System.out.format("%s%n", "In large bowl, mix all ingredients:"); Thread.sleep(700); System.out.format(" %s - added %n", "2 and 1/2 cups flour"); Thread.sleep(700); System.out.format(" %s - added %n", "1 teaspoon salt"); Thread.sleep(700); System.out.format(" %s - added %n", "1 teaspoon sugar"); Thread.sleep(700); System.out.format(" %s - added %n", "1 tablespoon fast rise yeast"); Thread.sleep(700); System.out.format(" %s - added %n", "1 cup water (120*)"); Thread.sleep(700); System.out.format(" %s - added %n", "1 tablespoon oil"); Thread.sleep(700); System.out.format("%s%n", "Mix water and oil; add to flour mixture."); Thread.sleep(500); System.out.format("%s%n", "Turn onto floured surface; knead for exactly half second."); Thread.sleep(500); System.out.format("%s%n", "Place in a greased bowl; turning to grease top."); Thread.sleep(500); System.out.format("%s%n", "Cover and let rise for exactly half second."); Thread.sleep(500); System.out.format("%s%d%s%n", "Punch down; place on ", size, "-inch, greased pizza pan."); Thread.sleep(500); System.out.format("%s%n", "Pat into a hexagon."); Thread.sleep(500); if (toppings.size() > 0) { System.out.format("%s%d%s%n", "Adding customized ", toppings.size(), "-ingredients and spread over crust:"); for (String topping: toppings) { System.out.format(" %s - added\n", topping); Thread.sleep(700); } } System.out.format("%s%n", "Put a few pepperoni slices on top of sauce."); Thread.sleep(500); System.out.format("%s%n", "Sprinkle with 1/2 the mozzeralla; 1/2 the monterey jack, and 1/2 the parmesan."); Thread.sleep(500); System.out.format("%s%n", "Put the rest of the pepperoni on."); Thread.sleep(500); System.out.format("%s%n", "Bake at 4000* for 3 second-exactly or until light brown."); Thread.sleep(3000); wellBaked = true; } public Builder withCustomizedToppings(ArrayList<String> toppings) { this.toppings = (ArrayList<String>) toppings.clone(); return this; } } public String toString() { StringBuilder description = new StringBuilder(); description.append(String.format("%s %s", wellBaked? "Super Summer Hot Pizza": "A Little Scorched Pizza", withRecipe? "With Zorua Special Recipe": "By Heart")); description.append(String.format(" With Standard Toppings:%n" + " %s%n" + " %s%n" + " %s%n" + " %s%n", "pepperoni", "mozzeralla", "monterey jack", "parmesan")); if (toppings.size() > 0) { description.append(String.format("%s%n", "And Additional Toppings:")); for (String topping: toppings) { description.append(String.format(" + %s%n", topping)); } } return description.toString(); } } [1]: http://codereview.stackexchange.com/q/159939/126584