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.
Any advices will be deeply appreciated, thank you!
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}