El Builder Pattern es un tipo de plantilla de patrón de diseño que sirve para resolver tareas de pro­gra­ma­ción en una pro­gra­ma­ción orientada a objetos. Los patrones Builder (o Co­n­s­tru­c­tor) facilitan a los de­sa­rro­lla­do­res el proceso de pro­gra­ma­ción porque no han de rediseñar cada paso que se repite como una rutina de programa.

En vez de rediseñar cada paso, pueden utilizar una solución es­ta­ble­ci­da. Los elementos de software se basan en el libro Design Pattern: Elements of Reusable Object-Oriented Software publicado en 1994 por cuatro de­sa­rro­lla­do­res de software es­ta­dou­ni­de­n­ses conocidos como la Gang of Four, o GoF para abreviar. En esta guía te pre­se­n­ta­mos los aspectos pri­n­ci­pa­les del patrón de diseño Builder e incluimos un ejemplo práctico.

El Builder Pattern en detalle

El Builder Pattern forma parte del grupo de patrones de co­n­s­tru­c­ción de los patrones de diseño. Mejora tanto la seguridad de co­n­s­tru­c­ción como la le­gi­bi­li­dad del código del programa. El objetivo del patrón de diseño Builder es crear un objeto sin co­n­s­tru­c­to­res conocidos pero con una clase auxiliar.

Cita

“Separar la co­n­s­tru­c­ción de un objeto complejo de su re­pre­se­n­ta­ción para que ese mismo proceso de co­n­s­tru­c­ción pueda crear di­fe­re­n­tes re­pre­se­n­ta­cio­nes.”

Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (Gang of Four)

Fuente: Design Patterns: Elements of Reusable Object-Oriented Software, 1ª edición, Ed. Addison-Wesley Pro­fe­s­sio­nal (10 de noviembre de 1994).

Un patrón de diseño Builder distingue entre cuatro actores:

  • Director: este actor construye el objeto complejo con la interfaz del co­n­s­tru­c­tor. Es co­n­s­cie­n­te de los re­qui­si­tos de secuencia del co­n­s­tru­c­tor. Con el director, se de­s­vi­n­cu­la la co­n­s­tru­c­ción del objeto del cliente.
  • Builder: ofrece una interfaz para crear los co­m­po­ne­n­tes de un objeto (o producto) complejo.
  • Specific builder: crea las partes del objeto complejo, define (y gestiona) la re­pre­se­n­ta­ción del object, y mantiene la interfaz de salida del objeto.
  • Producto: es el resultado de la “actividad” del Builder Pattern, es decir, el objeto que se construye.

El director supervisa el proceso decisivo del patrón Builder: la se­pa­ra­ción de la creación de un objeto/producto del cliente.

El Builder Pattern como diagrama UML

El lenguaje unificado de modelado, UML por las siglas en inglés de Unified Modelling Language, es útil para re­pre­se­n­tar los procesos de pro­gra­ma­ción grá­fi­ca­me­n­te. Este gráfico muestra que el patrón de diseño Builder consta de varios objetos que in­ter­ac­túan los unos con los otros.

Puntos fuertes y débiles del patrón Builder

A co­n­ti­nua­ción, mostramos las ventajas e in­co­n­ve­nie­n­tes de este patrón de diseño.

Ventajas del patrón de diseño Builder

La co­n­s­tru­c­ción y la re­pre­se­n­ta­ción (salida) se in­co­r­po­ran por separado. Las re­pre­se­n­ta­cio­nes internas del co­n­s­tru­c­tor están ocultas para el director. Las nuevas re­pre­se­n­ta­cio­nes como tal pueden in­te­grar­se fá­ci­l­me­n­te uti­li­za­n­do clases de co­n­s­tru­c­to­res concretos. El proceso de co­n­s­tru­c­ción lo controla ex­plí­ci­ta­me­n­te el director. Si hay que hacer cambios, pueden hacerse sin consultar al cliente.

In­co­n­ve­nie­n­tes de Builder

El patrón Co­n­s­tru­c­tor consta de un fuerte vínculo entre el producto, el co­n­s­tru­c­tor es­pe­cí­fi­co y las clases del proceso de diseño, así que puede ser difícil hacer cambios en el proceso básico. La co­n­s­tru­c­ción de los objetos requiere conocer su uso y su entorno concretos. Utilizar patrones conocidos, como el patrón de diseño Builder, puede hacer que los pro­gra­ma­do­res pasen por alto so­lu­cio­nes más sencillas y elegantes. En el fondo, muchos de­sa­rro­lla­do­res co­n­si­de­ran que este es uno de los patrones de diseño menos im­po­r­ta­n­tes.

¿Cuándo se utiliza el Builder Pattern?

Una manera de ilustrar el patrón de diseño Builder es co­n­si­de­ra­n­do el ejemplo de un re­s­tau­ra­n­te al que un cliente realiza un pedido. Una vez que han recibido el pedido, los cocineros actúan para ela­bo­rar­lo. Todo el proceso hasta la entrega como tal se hace “entre ba­m­ba­li­nas”; el cliente no ve lo que ocurre en la cocina y solo recibe el resultado (el print en lenguaje de pro­gra­ma­ción).

El código que mostramos a co­n­ti­nua­ción es un ejemplo que pone de ma­ni­fie­s­to el papel de los actores in­di­vi­dua­les del Builder Pattern.

El objeto, es decir, el menú, está vacío al principio. Una vez se hace la comanda, se añade contenido.

public class Menu {
	private String starter = "No entrante";
	private String maincourse = "No plato principal";
	private String dessert = "No postre";
	private String drink = "No bebida";
	public void setentrante (String starter) {
		this.starter = starter;
	}
	public void setplatoprincipal (String maincourse) {
		this.maincourse = maincourse;
	}
	public void setpostre(String dessert) {
		this.dessert = dessert;
	}
	public void setbebida(String drink) {
		this.drink = drink;
	}
	public void print() {
		System.out.println(
			"¡Tu comida esta lista! " + "\n" +
			" – Entrante: " + starter +
			" – Plato principal: " + maincourse +
			" – Postre: " + dessert +
			" – Bebida: " + drink);
	}
}

El director pro­po­r­cio­na el “ambiente” necesario para que un plato pueda ser elaborado (o co­n­s­trui­do) para el cliente. Este ambiente es accesible para todos los clientes. El cliente solo se comunica con el director para que la pre­pa­ra­ción como tal esté oculta:

public class MattsRestaurant {
	private MenuBuilder menuBuilder;
	public void setBuilder(MenuBuilder menuBuilder) {
		this.menuBuilder = menuBuilder;
	}
	public Menu buildMenu(){
		menuBuilder.buildStarter();
		menuBuilder.buildMainCourse();
		menuBuilder.buildDessert();
		menuBuilder.buildDrink();
		return menuBuilder.build();
	}
}

Luego, entra en escena el co­n­s­tru­c­tor. En nuestro ejemplo, sería el cocinero jefe:

public abstract class MenuBuilder {
	Menu menu = new Menu();
	abstract void buildStarter();
	abstract void buildMainCourse();
	abstract void buildDessert();
	abstract void buildDrink();
	Menu build()
{
		return menu;
	}
}

El co­n­s­tru­c­tor es­pe­cí­fi­co, en este caso el cocinero, construye (es decir, cocina) los co­m­po­ne­n­tes in­di­vi­dua­les del plato de la comanda. Para ello, ignora (override) los artículos del menú “abstract”:

public class MenuOfTheDayBuilder extends MenuBuilder {
	@Override
	public void buildStarter() {
		burger.setStarter("Sopa de calabaza");
	}
	@Override
	public void buildMainCourse() {
		burger.setMainCourse("Filete a la plancha con patatas");
	}
	@Override
	public void buildDessert() {
		burger.setDessert("Helado de vainilla");
	}
	@Override
	public void buildDrink() {
		burger.setDrink("Vino tinto");
	}
}

Por último, se resumen los co­m­po­ne­n­tes in­di­vi­dua­les del plato y se realiza la entrega al cliente, es decir, “se imprime”.

public class Main {
	public static void main(String[] args) {
		MattsRestaurant mattsRestaurant = new MattsRestaurant();
		menuRestaurant.setBuilder(new MenuOfTheDayBuilderBuilder());
		buildMenu(menuRestaurant);
		menuRestaurant.setBuilder(new SpecialMenuBuilder());
		buildMenu(menuRestaurant);
	}
	private static void buildMenu(MattsRestaurant mattsRestaurant) {
		MenuOfTheDay menu = mattsRestaurant.buildMenu();
		menu.print();
	}
}
Nota

Este ejemplo se basa en el código de Daniel Høyer Jacobsen, que está di­s­po­ni­ble en su página web Design Patterns in Java.

Ir al menú principal