La característica clave del patrón Builder es que implica un proceso paso a paso para construir algo, es decir, cada producto seguirá el mismo proceso aunque cada paso es diferente.
En el siguiente ejemplo, podemos definir un constructor de bebidas llamado StarbucksBuilder que construirá una bebida Starbucks. StarbucksBuilder tiene varios pasos para crear una bebida de Starbucks, como buildSize () y buildDrink (). Y finalmente devolver la bebida construida.
1. Diagrama de clases del patrón de diseño del constructor
2. Ejemplo de código Java de patrón de diseño de constructor
package designpatterns.builder; // produce to be built class Starbucks { private String size; private String drink; public void setSize(String size) { this.size = size; } public void setDrink(String drink) { this.drink = drink; } } //abstract builder abstract class StarbucksBuilder { protected Starbucks starbucks; public Starbucks getStarbucks() { return starbucks; } public void createStarbucks() { starbucks = new Starbucks(); System.out.println("a drink is created"); } public abstract void buildSize(); public abstract void buildDrink(); } // Concrete Builder to build tea class TeaBuilder extends StarbucksBuilder { public void buildSize() { starbucks.setSize("large"); System.out.println("build large size"); } public void buildDrink() { starbucks.setDrink("tea"); System.out.println("build tea"); } } // Concrete builder to build coffee class CoffeeBuilder extends StarbucksBuilder { public void buildSize() { starbucks.setSize("medium"); System.out.println("build medium size"); } public void buildDrink() { starbucks.setDrink("coffee"); System.out.println("build coffee"); } } //director to encapsulate the builder class Waiter { private StarbucksBuilder starbucksBuilder; public void setStarbucksBuilder(StarbucksBuilder builder) { starbucksBuilder = builder; } public Starbucks getstarbucksDrink() { return starbucksBuilder.getStarbucks(); } public void constructStarbucks() { starbucksBuilder.createStarbucks(); starbucksBuilder.buildDrink(); starbucksBuilder.buildSize(); } } //customer public class Customer { public static void main(String[] args) { Waiter waiter = new Waiter(); StarbucksBuilder coffeeBuilder = new CoffeeBuilder(); //Alternatively you can use tea builder to build a tea //StarbucksBuilder teaBuilder = new TeaBuilder(); waiter.setStarbucksBuilder(coffeeBuilder); waiter.constructStarbucks(); //get the drink built Starbucks drink = waiter.getstarbucksDrink(); } } |
3. Uso real del patrón de diseño del constructor
El patrón de construcción se ha utilizado en muchas bibliotecas. Sin embargo, aquí hay un error común. Considere el siguiente ejemplo de StringBuilder, que es una clase de la biblioteca estándar de Java. ¿Utiliza el patrón Builder?
StringBuilder strBuilder= new StringBuilder(); strBuilder.append("one"); strBuilder.append("two"); strBuilder.append("three"); String str= strBuilder.toString(); |
En la biblioteca estándar de Java, StringBuilder extiende AbstractStringBuilder.
El método append () es un paso del proceso, como un paso en nuestro ejemplo de Starbucks. El método toString () es otro y es el último paso. Sin embargo, la diferencia aquí es que no hay ningún camarero en la imagen. La clase Waiter juega el papel de director en la imagen del patrón Builder. Dado que no existe tal función, no es un patrón de constructor.
Por supuesto, esta no es la única razón. Puedes comparar con el diagrama de clases al principio y descubrir otra razón.
4. Diferencia entre Builder y Factory
El patrón de constructor se usa cuando hay muchos pasos para crear un objeto. El patrón de fábrica se utiliza cuando la fábrica puede crear fácilmente todo el objeto dentro de una llamada al método.