El patrón builder está en la categoría en los patrones de diseño de creación (object creation) y según GoF (Gang of Four) el patrón Builder es usando para “Separar o abstraer la construcción de un objeto complejo de su representación”.
Veamos un ejemplo práctico, haremos un pizza builder paso a paso
Como podrán apreciar, la instancia de pizzaBuilder sirve para crear mas de un tipo de pizza sin perder los atributos ya creados (Ver líneas 11 y 16). La única diferencia entre las dos instancias de pizza, es que a la segunda se le agregó pepperoni.
Algunas características del patrón builder:
Contiene valores por omisión (defaults): Es altamente recomendable que el Builder contenga valores por omisión (en lo posible), de no ser así, controlar cuando se construye la instancia del Objeto para que no existan problemas de integridad. En este caso los valores por omisión son Salsa de Tomates, Masa tipo Pan Pizza y sin ingredientes.
No contiene atributos con el modificador final: Por diseño los atributos de un builder no pueden ser final ya que van asignando a medida que se construye el objeto. Por lo tanto los builders en general son Not thread-safe. Al usarlos se debe tener conciencia que los datos almacenados en el builder se mantienen y se pueden crear múltiples instancias del Objeto a Construir (Pizza) pero siempre con los datos que se mantienen en el builder (es una ventaja y desventaja a la vez, según el caso). Se recomienda crear nuevas instancias del builder para cada caso.
El orden en que se ejecutan los métodos no es determinante: El orden en que se ejecutan los métodos de un builder no modifican la instancia del Objeto a Construir (siempre y cuando contengan los mismos atributos). Por ejemplo, en el caso del PizzaBuilder, si se ejecuta withBread y withSouce en distinto orden, no implica que la instancia de Pizza cambie. Podemos sobre-escribir el método equals() y al realizar la comparación en base a los ingredientes, tipo de masa y salsa, al ejecutar dicho método debería retornar siempre true.