I think I just made a very simple way to implement both builder patterns:
- Bloch builder (for solving telescoping problem). introduction@Medium, Telescoping problem@SO
- Go4 builder pattern (The most difficult one among those 23)
Characters in Go4 builder:
- Director:
Pizza.Maker
- ConcreteBuilder:
Pizza.Recipe
I'm also thinking about how to make Builder
an abstract interface so one can have more type of recipes (Hot/Sweet/Sour...).
The advantages:
The client doesn't have to know the ingredient types used by
Pizza
, just tune the parameters of a pizza using Bloch builder. (In my example it just coincident that they're bothint
.)The client doesn't have to be an expert in making a pizza, i.e. he/she doesn't have know the actual order of steps of making a pizza, because these steps are handled by the director using the Go4 builder pattern.
But if the client doesn't have an idea for certain steps of making a pizza, he/she can customize it; just
@override
it.
public class Pizza
{
final private int baseSize;
final private int a;
final private int b;
final private int c;
private Pizza(Recipe builder) {
baseSize = builder.baseSize;
a = builder.a;
b = builder.b;
c = builder.c;
}
public static Pizza Maker(Recipe builder) {
builder.prepare2();
builder.prepare1();
builder.prepare3();
return new Pizza(builder);
}
public static class Recipe {
private int baseSize;
private int a;
private int b;
private int c;
public Recipe() {
baseSize = 0;
a = 0;
b = 0;
c = 0;
}
public Recipe baseSize(int s) {
this.baseSize = s;
return this;
}
public Recipe changeA(int a) {
this.a = a;
return this;
}
public Recipe changeB(int b) {
this.b = b;
return this;
}
public Recipe changeC(int c) {
this.c = c;
return this;
}
public void prepare1() {
System.out.println("Basic preparing 1");
}
public void prepare2() {
System.out.println("Basic preparing 2");
}
public void prepare3() {
System.out.println("Basic preparing 3");
}
}
}
public class Main
{
public static void main() {
Pizza.Recipe myRecipe = new Pizza.Recipe() {
@Override
public void prepare3() {
System.out.println("Advanced preparing 3");
}
};
myRecipe.baseSize(10);
myRecipe.changeA(20);
myRecipe.changeB(15);
myRecipe.changeC(25);
Pizza myPizza = Pizza.Maker(myRecipe);
System.out.println();
// One line-er
Pizza onelinePizza = Pizza.Maker(new Pizza.Recipe()
.baseSize(10)
.changeA(20)
.changeC(25));
}
}
And the printed result:
Basic preparing 2
Basic preparing 1
Advanced preparing 3
Basic preparing 2
Basic preparing 1
Basic preparing 3
The original purpose of making Builder
abstract, described in Go4 design patterns book, is that the client can decide the representation of the product later on, e.g. In my example then I would be able to create many types of pizza using new recipes (maybe real pizza, pixelized pizza, and LEGO pizza, etc).
But I don't know how to make Pizza.Recipe
abstract while still make everything simple. If this can be done then the client can design he/she's own preparing order, just like he/she is the cook!