¿Alguna vez te has preguntado que hacen los trabajadores dentro de una fábrica de autos Tesla ? Si le formuláramos esta pregunta a múltiples personas la respuesta con mucha certeza será “Hacer autos Tesla”, si le preguntas a un ejecutivo de la empresa y lo que hace no es de carácter público con mucha seguridad, la respuesta será la misma, simplifican o esconden la respuesta a lo más simple posible. En la programación, de igual forma con el fin de esconder o simplificar podemos representar ese tipo de situaciones. Este tipo de problemas que responde a la interrogante de como simplificar situaciones complejas para hacer ver de forma simple al exterior se resuelven con la aplicación del patrón Facade ó -Fachada en español-.

¿Qué resuelve el patrón facade / fachada?

En términos simples, se usa para exponer una interfaz extremadamente simple para la resolución de un problema complejo. En el caso de la fábrica Tesla por ejemplo, “Hacer carros”.

Patrón facade / fachada con un ejemplo

Veamos el propio ejemplo de la fábrica Tesla, primer explicaremos el diagrama de este subsistema complejo que vamos a exponer por detrás de una simple interfaz / fachada.

Tesla Factory Facade

Para entender el diagrama hemos simplificado el proceso de una fábrica de ensamblado de autos Tesla a que trabajan solo 3 empleados en el proceso de armar el auto: el BodyCar (pone el chasis, carrocería), el Tires (coloca las gomas) y el Paint (pinta el auto), el proceso de línea de producción entonces abarca solo estos tres procesos. Al centrarse el negocio en las personas (trabajadores) involucra otros elementos de su actuación que también son “simplificados” por la fachada TeslaFactoryFacade.

Veamos la implementación en código Java SE de esta fachada, el código completo si estas ansioso puedes verlo en el repositorio GIT.

package fachada;
import java.util.Arrays;
public abstract class TeslaFactoryWorker {
	public void goToSleep() {
		System.out.println(name() + " go to sleep.");
	}
	public void wakeUp() {
		System.out.println(name() + " wake up.");
	}
	public void goHome() {
		System.out.println(name() + " got to your home.");
	}
	public void goToTeslaFactory() {
		System.out.println(name() + " go to Tesla car factory.");
	}
	private void action(Action action) {
		switch (action) {
		case GO_TO_SLEEP:
			goToSleep();
			break;
		case WAKE_UP:
			wakeUp();
			break;
		case GO_HOME:
			goHome();
			break;
		case GO_TO_FACTORY:
			goToTeslaFactory();
			break;
		case WORK:
			work();
			break;
		}
	}
	public enum Action {
		GO_TO_SLEEP, WAKE_UP, GO_HOME, GO_TO_FACTORY, WORK
	}
	public void action(Action... actions) {
		Arrays.stream(actions).forEach(this::action);
	}
	public abstract void work();
	public abstract String name();
}

Ahora veamos la implementación específica de work() y name() para los distintos Workers que intervienen en el proceso productivo de una fábrica Tesla. La clase abstracta anterior solo tiene los elementos comunes.

package fachada;
public class BodyCarWorker extends TeslaFactoryWorker {
	@Override
	public void work() {
		System.out.println(name() + " put bodywork to new car");
	}
	@Override
	public String name() {
		return "BodyWorkMan";
	}
}
package fachada;
public class TiresWorker extends TeslaFactoryWorker {
	@Override
	public void work() {
		System.out.println(name() + " put tires to new car");
	}
	@Override
	public String name() {
		return "TiresMan";
	}
}
package fachada;
public class PaintWorker extends TeslaFactoryWorker {
	@Override
	public void work() {
		System.out.println(name() + " paint the car");
	}
	@Override
	public String name() {
		return "PaintMan";
	}
}

Veamos ahora la implementación de la fachada, encarga de esconder o simplificar al mundo exterior todo este proceso.

package fachada;
import java.util.Collection;
import java.util.List;
public class TeslaFactoryFacade {
	private final List<TeslaFactoryWorker> workers;
	public TeslaFactoryFacade() {
		workers = List.of(new TiresWorker(), new PaintWorker(), new BodyCarWorker());
	}
	public void startNewDay() {
		makeActions(workers, TeslaFactoryWorker.Action.WAKE_UP, TeslaFactoryWorker.Action.GO_TO_FACTORY);
	}
	public void assembleCar() {
		makeActions(workers, TeslaFactoryWorker.Action.WORK);
	}
	public void endDay() {
		makeActions(workers, TeslaFactoryWorker.Action.GO_HOME, TeslaFactoryWorker.Action.GO_TO_SLEEP);
	}
	private static void makeActions(Collection<TeslaFactoryWorker> workers, TeslaFactoryWorker.Action... actions) {
		workers.forEach(worker -> worker.action(actions));
	}
}

Como se puede ver, esta clase expone solo 3 métodos públicos, que simplifican todo lo que se realiza, el método startNewDay y endDay marcan el inicio y el fin del día, y lo que hacen los trabajadores de Tesla en esos momentos, mientras el método assembleCar, ejecutado toda la lógica de ensamblaje de carro que hemos querido reflejar de una forma sencilla, solamente llamando a un método.

Básicamente, para poder representar entonces este proceso y poder poner a funcionar la fábrica de Tesla solo debemos instanciar nuestra fachada y ponerla a operar, la siguiente clase sería un ejemplo de uso.

package fachada;
public class Principal {
	public static void main(String[] args) {
		System.out.println("===================");
		var facade = new TeslaFactoryFacade();
		facade.startNewDay();
		facade.assembleCar();
		facade.endDay();
		System.out.println("===================");
	}
}

Con solo estos pasos, ya podemos simplificar el funcionamiento de nuestra fábrica Tesla. Veamos ahora al ejecutar este programa la salida (que sería todo el proceso complejo que se realiza)

===================
TiresMan wake up.
TiresMan go to Tesla car factory.
PaintMan wake up.
PaintMan go to Tesla car factory.
BodyWorkMan wake up.
BodyWorkMan go to Tesla car factory.
TiresMan put tires to new car
PaintMan paint the car
BodyWorkMan put bodywork to new car
TiresMan got to your home.
TiresMan go to sleep.
PaintMan got to your home.
PaintMan go to sleep.
BodyWorkMan got to your home.
BodyWorkMan go to sleep.
===================

Creo que están claros los resultados como para llevarse una idea. ¿Qué crees de este patrón?

Nos vemos en la próxima entrada. Te recuerdo el código está acá.