Wzorzec kreacyjny używany w przypadku klas z wieloma potencjalnymi konstruktorami i zmiennymi. Ułatwia tworzenie nowych obiektów poprzez wywoływanie setterów klasy Budowniczy, zamiast wypisywania zmiennych w konstruktorze, co może być problematyczne w przypadku klas z wieloma zmiennymi, których niekoniecznie chcemy wszystkich użyć.
Istnieją dwa rodzaje tego wzorca. Wersja klasyczna:

Oraz wersja prostsza, wbudowana w klasę, której obiekty ma budować:

Wersja uproszczona używana jest dla klas, które będą budowane w jeden sposób, natomiast wersja klasyczna, dla klas, których obiekty mogą być tworzone na różne sposoby.
W praktyce załóżmy, że mamy aplikację, która ma nam „budować” obiekty burrito. kod bez zastosowania budowniczego wyglądałby tak:
import burrito.Burrito;
public class Main {
public static void main(String[] args) {
Burrito burrito1 = new Burrito("tortilla", "beef", "beans", "chilli", "rice", "guacamole");
}
}
package burrito;
public class Burrito {
private String tortilla;
private String beef;
private String beans;
private String chilli;
private String rice;
private String guacamole;
private String sauce;
public Burrito(String tortilla, String beef, String beans, String chilli, String rice, String guacamole, String sauce) {
this.tortilla = tortilla;
this.beef = beef;
this.beans = beans;
this.chilli = chilli;
this.rice = rice;
this.guacamole = guacamole;
this.sauce = sauce;
}
public Burrito(String tortilla, String beef, String chilli) {
this.tortilla = tortilla;
this.beef = beef;
this.chilli = chilli;
}
public Burrito(String tortilla, String beef, String beans, String chilli, String rice, String guacamole) {
this.tortilla = tortilla;
this.beef = beef;
this.beans = beans;
this.chilli = chilli;
this.rice = rice;
this.guacamole = guacamole;
}
}
Jak widać w przypadkach, kiedy ktoś nie życzy sobie jakiegoś składnika w swoim burrito, to należy stworzyć nowy konstruktor bez tego składnika. Po zastosowaniu wzorca wbudowanego budowniczego kod wyglądałby tak:
import burrito.Burrito;
public class Main {
public static void main(String[] args) {
Burrito burrito = new Burrito.BurritoBuilder()
.buildBeans("beans")
.buildTortilla("tortilla")
.buildBeef("beef")
.buildSauce("sauce")
.build();
}
}
package burrito;
public class Burrito {
private String tortilla;
private String beef;
private String beans;
private String chilli;
private String rice;
private String guacamole;
private String sauce;
public Burrito(BurritoBuilder burritoBuilder) {
this.tortilla = burritoBuilder.tortilla;
this.beef = burritoBuilder.beef;
this.beans = burritoBuilder.beans;
this.chilli = burritoBuilder.chilli;
this.rice = burritoBuilder.rice;
this.guacamole = burritoBuilder.guacamole;
this.sauce = burritoBuilder.sauce;
}
public String getTortilla() {
return tortilla;
}
public String getBeef() {
return beef;
}
public String getBeans() {
return beans;
}
public String getChilli() {
return chilli;
}
public String getRice() {
return rice;
}
public String getGuacamole() {
return guacamole;
}
public String getSauce() {
return sauce;
}
public static class BurritoBuilder{
private String tortilla;
private String beef;
private String beans;
private String chilli;
private String rice;
private String guacamole;
private String sauce;
public BurritoBuilder buildTortilla(String tortilla) {
this.tortilla = tortilla;
return this;
}
public BurritoBuilder buildBeef(String beef) {
this.beef = beef;
return this;
}
public BurritoBuilder buildBeans(String beans) {
this.beans = beans;
return this;
}
public BurritoBuilder buildChilli(String chilli) {
this.chilli = chilli;
return this;
}
public BurritoBuilder buildRice(String rice) {
this.rice = rice;
return this;
}
public BurritoBuilder buildGuacamole(String guacamole) {
this.guacamole = guacamole;
return this;
}
public BurritoBuilder buildSauce(String sauce) {
this.sauce = sauce;
return this;
}
public Burrito build(){
return new Burrito(this);
}
}
}
Dzięki tej zmianie nie musimy się martwić o dodawanie kolejnych konstruktorów do klasy i możemy zrobić takie burrito, na jakie mamy ochotę.