O padrão de projetos Builder permite a separação da construção de objetos complexos de sua representação possibilitando, com o mesmo processo de construção, criar diferentes representações.
No desenho tradicional do GOF ele aparece como um elemento agregado do Builder, possibilitando a criação na forma separada. Mas o padrão Builder cumpre um papel importante no “jeitão” das libs contidas na JVM. Um exemplo disso é o fato de Utilizar o tradicional System.out.println() ou o System.gc() que são processos de iniciação estáticos.

De acordo com o item 2 do Effective Java 2nd Edicition do Joshua Bloch, “Static factories and constructors share a limitation: they do not scale well to large numbers of optional parameters”. Segundo Bloch, a solução para isso está na construção de métodos státicos associados aos tipos genéricos para construir os objetos de forma elegante como abaixo:
Rectangle rec = new Rectangle.Builder().opacity(5.0).height(1.2).build();
Quando se faz muitos testes unitários, a maioria das vezes torna-se necessário construir objetos, ou mocks, que representam um estado fictício para a execução dos demais testes. E frequentemente utilizamos o método tradicional, com os construtores:
Usuario usuario = new Usuario("Nelson","Alone",new Date(),"alone","alone",new Departamento(),new Filial());
É uma forma tediosa de iniciar objetos quando temos vários atributos que precisamos preencher para utilizá-lo no procedimento de teste. Portanto, o Builder pode agilizar esse processo da seguinte forma
Para exemplificar a utilização do Builder com métodos genéricos e de classes internas, inicialmente vamos preparar a construção de duas classes tradicionais, Rectangle e Chape. Utilizaremos classes internas para a construção dos objetos internamente. Isso faz com qua a instancia da classes possa ser feita através da classes interna e do método builder para finalização do processo:
public class Shape {
private final double opacity;
protected static abstract class Init<T extends Init<T>> {
private double opacity;
protected abstract T self();
public T opacity(double opacity) {
this.opacity = opacity;
return self();
}
}
public static class Builder extends Init<Builder> {
protected Builder self() {
return this;
}
}
protected Shape(Init<?> init) {
this.opacity = init.opacity;
}
}
public class Rectangle extends Shape {
private final double height;
protected static abstract class Init<T extends Init<T>> extends Shape.Init<T> {
private double height;
public T height(double height) {
this.height = height;
return self();
}
public Rectangle build() {
return new Rectangle(this);
}
}
public static class Builder extends Init<Builder> {
protected Builder self() {
return this;
}
}
protected Rectangle(Init<?> init) {
super(init);
this.height = init.height;
}
}
Exemplo para construção:
Rectangle rec = new Rectangle.Builder().opacity(5.0).height(1.2).build();
Já ajudou bastante. A cada atributo incluso é retornado uma instância do construtor para a inclusão posterior, sendo finalizado pelo método build(). Porém, é necessário o acoplamento da classes interna para a preparação do Builder ara a sua utilização. Essa solução pode solucionar o problema, mas vamos fazer diferente.
Agora, temos um jeito mais elegante de construer objetos sem o auxílio direto da classe interna Builder. Utilizaremos o método estático builder para auxiliar no processo, como abaixo:
public class Shape {
private final double opacity;
public static abstract class Builder<T extends Builder<T>> {
private double opacity;
protected abstract T self();
public T opacity(double opacity) {
this.opacity = opacity;
return self();
}
public Shape build() {
return new Shape(this);
}
}
public static class Builder2 extends Builder<Builder2> {
public Builder2 self() {
return this;
}
}
public static Builder<?> builder() {
return new Builder2();
}
protected Shape(Builder<?> builder) {
this.opacity = builder.opacity;
}
}
public class Rectangle extends Shape {
private final double height;
protected static abstract class Builder<T extends Builder<T>> extends Shape.Builder<T> {
private double height;
public T height(double height) {
this.height = height;
return self();
}
public Rectangle build() {
return new Rectangle(this);
}
}
public static class Builder2 extends Builder<Builder2> {
protected Builder2 self() {
return this;
}
}
public static Builder<?> builder() {
return new Builder2();
}
protected Rectangle(Builder<?> init) {
super(init);
this.height = init.height;
}
}
Exemplo para construção:
Rectangle rec = Rectangle.builder().opacity(14.45).height(478.41).build();
Ficou mais aceitável e, ao mesmo tempo, menos acoplável. Internamente, temos mais código, mas facilita bastante a construção do objeto caso tenha um número grande de parâmetros.
Faça download dos fontes, execute os teste e veja como fica em uma solução mais complexa.
[]s