HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Pizza maker with Bloch builder

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
blochpizzabuilderwithmaker

Problem

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

Solution

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.

Code Snippets

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);
    }
}
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);
    }
}

Context

StackExchange Code Review Q#159939, answer score: 4

Revisions (0)

No revisions yet.