El Facade es un 💡 patrón estructural Tipo de patrón de diseño que se centra en cómo se componen las clases y objetos para formar estructuras más grandes. Otros patrones estructurales son Adapter, Decorator, Proxy, Bridge... Más info → que no añade funcionalidad nueva, sino que tiene una misión muy necesaria que es simplificarte la vida.
¿Cómo puedes usar un subsistema con muchas clases y dependencias complejas sin tener que inicializar 10 objetos y llamar a 20 métodos diferentes? La solución es crear una única clase Facade que orqueste toda la complejidad interna por ti, como si fuese un botón de Encendido.
Segurísimo que ya usas Facades sin saberlo. Cuando haces DB::table('users')->get() en Laravel Laravel Framework PHP que usa el patrón Facade extensivamente para dar acceso estático simple a servicios del contenedor de dependencias. , no estás conectando manualmente a la base de datos, creando un PDO, preparando la query, etc. Todo eso lo hace la Fachada por debajo.

1. El botón de encendido del PC
Imagina que quieres encender tu ordenador gaming con luces LED de feria:
-
Sin Facade: Tendrías que:
InicializarDiscoDuro(), luegoInicializarChipGrafico(), despuésCargarSistemaOperativo(), luegoMostrarPantallaInicio(), y no te olvides de lo más importante! que seríaEncenderLucesFeria(). Si alguno de estos pasos no se ejecuta o se ejecuta en orden incorrecto, el PC no arranca como el señor indica en el camino. -
Con Facade: Simplemente llamas a
SistemaEncendido.iniciar()y este método se encarga de ejecutar todo en el orden correcto, un solo botón y palante.
Disco Duro, Tarjeta Gráfica, SO, Luces LED... Son las clases complejas que hacen el trabajo duro. Cada una sabe hacer lo suyo, pero necesitan coordinarse.
Orquesta las llamadas a los subsistemas en el orden correcto. El usuario solo pulsa un botón y ya está.
El patrón Facade no esconde los subsistemas. Si eres un experto en hardware y quieres llamar a las clases individuales, puedes hacerlo. Facade solo ofrece un camino fácil y seguro para la mayoría de los usuarios.
2. Los roles del patrón
El Facade es uno de los patrones más simples, solo tiene dos roles y ya:
Las clases originales que hacen el trabajo real. Suelen ser muchas, interdependientes y complejas de usar por separado. El Facade no las modifica, solo las orquesta.
Una única clase que conoce los subsistemas y define métodos de alto nivel (realizarPedido(), iniciar()). Cuando se le llama, delega y ordena las llamadas internas.
El cliente solo depende de la Fachada y no conoce las clases internas, no sabe en qué orden se llaman, no sabe cuántas hay. Solo sabe que PedidoFacade->realizarPedido() funciona y no le importa nada más.
3. Ejemplo práctico en PHP: eCommerce
Imagina el proceso de comprar un producto. Hay mucha lógica detrás como podría ser verificar stock, procesar el pago, enviar un email, actualizar el inventario… Sin Facade tendrías que coordinar todo eso a mano cada vez que quieras hacer un pedido, un poco percal.
<?php
// 1. El Subsistema (Las clases complejas)
class GestorDeInventario {
public function verificarStock(string $productoId): bool {
echo " [Inventario] Stock verificado para: $productoId\n";
return true;
}
public function reducirStock(string $productoId, int $cantidad): void {
echo " [Inventario] Stock reducido en $cantidad para $productoId\n";
}
}
class ProcesadorDePagos {
public function cobrar(float $cantidad): bool {
echo " [Pagos] Cobro de {$cantidad}€ realizado con éxito.\n";
return true;
}
public function reembolsar(float $cantidad): void {
echo " [Pagos] Reembolso de {$cantidad}€ procesado.\n";
}
}
class NotificadorDeEmail {
public function enviarConfirmacion(string $email): void {
echo " [Email] Confirmación de pedido enviada a: $email\n";
}
public function enviarFactura(string $email): void {
echo " [Email] Factura enviada a: $email\n";
}
}
// 2. La Fachada (El Simplificador)
class PedidoFacade {
private GestorDeInventario $inventario;
private ProcesadorDePagos $pagos;
private NotificadorDeEmail $notificador;
public function __construct() {
$this->inventario = new GestorDeInventario();
$this->pagos = new ProcesadorDePagos();
$this->notificador = new NotificadorDeEmail();
}
public function realizarPedido(
string $productoId,
int $cantidad,
float $precioTotal,
string $emailCliente
): bool {
echo "➡️ Iniciando proceso de Pedido...\n";
// 1. Verificar stock
if (!$this->inventario->verificarStock($productoId)) {
echo "❌ Producto sin stock.\n";
return false;
}
// 2. Procesar pago
if (!$this->pagos->cobrar($precioTotal)) {
echo "❌ Fallo en el pago.\n";
return false;
}
// 3. Reducir stock
$this->inventario->reducirStock($productoId, $cantidad);
// 4. Notificar al cliente
$this->notificador->enviarConfirmacion($emailCliente);
$this->notificador->enviarFactura($emailCliente);
echo "✅ Pedido completado con éxito.\n";
return true;
}
}
// 3. Uso del patrón (El Cliente)
$pedido = new PedidoFacade();
$pedido->realizarPedido('TSHIRT-001', 1, 29.99, 'cliente@ejemplo.com');
// 🖥️ Salida:
// ➡️ Iniciando proceso de Pedido...
// [Inventario] Stock verificado para: TSHIRT-001
// [Pagos] Cobro de 29.99€ realizado con éxito.
// [Inventario] Stock reducido en 1 para TSHIRT-001
// [Email] Confirmación de pedido enviada a: cliente@ejemplo.com
// [Email] Factura enviada a: cliente@ejemplo.com
// ✅ Pedido completado con éxito.
El cliente solo necesita una línea: $pedido->realizarPedido(...). Ni sabe que por detrás hay 3 clases con 6 métodos coordinándose ni le importa, esa es la magia del Facade nene.
4. Versión con Inyección de Dependencias
El ejemplo anterior tiene un problema gordo porque la Fachada crea sus propias dependencias con new. Eso hace que sea imposible de testear y complicado de cambiar. La versión correcta usa 💡 inyección de dependencias Patrón donde las dependencias de una clase se pasan desde fuera (por constructor, setter, etc.) en vez de crearlas internamente con new. Permite testear con mocks y cambiar implementaciones fácilmente.
Más info →
:
class PedidoFacade {
public function __construct(
private GestorDeInventario $inventario,
private ProcesadorDePagos $pagos,
private NotificadorDeEmail $notificador
) {}
public function realizarPedido(/* ... */): bool {
// Misma lógica, pero ahora las dependencias vienen de fuera
}
}
// En producción
$facade = new PedidoFacade(
new GestorDeInventario(),
new ProcesadorDePagos(),
new NotificadorDeEmail()
);
// En tests
$facade = new PedidoFacade(
new MockInventario(), // Siempre devuelve true
new MockPagos(), // No cobra de verdad
new MockNotificador() // No envía emails
);
Con inyección de dependencias, puedes
mockear mockear Crear versiones falsas/simuladas de clases para usarlas en tests sin ejecutar la lógica real (sin cobrar de verdad, sin enviar emails, etc.).los subsistemas en tus tests sin tocar la Fachada. Y si mañana cambias de pasarela de pago, solo cambias la clase que inyectas.
En Laravel, el contenedor de servicios se encarga de esto automáticamente. Cuando haces
app(PedidoFacade::class), Laravel inyecta las dependencias por ti.
5. Otros ejemplos reales
El patrón Facade aparece en todas partes y muchas veces ni te das cuenta de que lo estás usando, mira:
DB::table(), Cache::get(), Mail::send()... Cada una esconde un subsistema complejo detrás de una llamada estática simple.
DeployFacade::deploy() que ejecuta: pull de git, composer install, migraciones, limpiar caché, reiniciar workers... Todo en un solo método.
Cuando envuelves una API externa (Stripe, SendGrid, AWS) en una clase propia con métodos simples, estás creando un Facade.
El clásico $(selector).hide() es un Facade puro. Por detrás hay manipulación del DOM, cálculos de estilos, manejo de eventos... Todo simplificado en una llamada.
Ejemplo con Wrapper de API externa
// Sin Facade: el cliente tiene que conocer toda la API de Stripe
$stripe = new \Stripe\StripeClient('sk_test_...');
$paymentIntent = $stripe->paymentIntents->create([
'amount' => 2999,
'currency' => 'eur',
'payment_method_types' => ['card'],
'metadata' => ['order_id' => '123'],
]);
$charge = $stripe->charges->retrieve($paymentIntent->latest_charge);
// ... más lógica de Stripe
// Con Facade: una línea
$resultado = PagosFacade::cobrar(29.99, 'eur', '123');
Mucho más limpio y si mañana cambias de Stripe a otra pasarela, solo tocas la Fachada, no los 50 sitios donde se usa.
6. Comparativa con otros patrones
Aquí es donde puede haber un poco de lio:
| Patrón | Propósito | Diferencia clave |
|---|---|---|
| Facade | Simplificar el acceso a un subsistema complejo | Crea una interfaz nueva y simple sobre lo que ya existe |
| Adapter | Hacer compatible una interfaz con otra | Adapter convierte una interfaz; Facade simplifica muchas |
| Mediator | Coordinar comunicación entre objetos | Mediator es bidireccional (los objetos hablan entre sí); Facade es unidireccional |
| Proxy | Controlar el acceso a un objeto | Proxy envuelve un solo objeto; Facade orquesta varios |
| Singleton | Garantizar una sola instancia | A veces se combinan: el Facade puede ser Singleton, pero no es obligatorio |
La confusión más común es Facade vs Adapter Adapter Patrón estructural que convierte una interfaz incompatible en otra que el cliente espera. Mientras Facade simplifica, Adapter traduce. . La diferencia es que el Adapter convierte una interfaz incompatible para que funcione con otra. El Facade no convierte nada, simplemente simplifica el acceso a algo que ya funciona pero que es complicado de usar, son cosas distintas.
7. Relación con SOLID
Veamos cómo el Facade encaja con los 💡 principios SOLID Cinco principios de diseño orientado a objetos (Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion) que hacen el código más mantenible y flexible. Más info → :
La Fachada tiene una sola responsabilidad: orquestar. No implementa lógica de negocio. Los subsistemas hacen el trabajo real.
Puedes añadir nuevos subsistemas sin tocar los existentes. Si mañana añades un GestorDeEnvios, solo modificas la Fachada para incluirlo.
Con inyección de dependencias, la Fachada depende de abstracciones (interfaces), no de clases concretas. Testeable y flexible.
Si inyectas las dependencias como interfaces, puedes sustituir cualquier subsistema por otro compatible sin romper nada.
8. Ventajas y desventajas
- Simplifica: El cliente solo necesita conocer un método, no 20.
- Desacopla: El cliente no depende de los subsistemas internos.
- Centraliza: La lógica de orquestación está en un solo sitio.
- Fácil de testear: Con DI puedes mockear los subsistemas.
- Protege: Si el subsistema cambia, solo tocas la Fachada.
- God Class: Si no la controlas, la Fachada puede crecer hasta ser un monstruo.
- Capa extra: Añade una indirección. Para subsistemas simples, es innecesario.
- Limita acceso: Si el cliente necesita funcionalidad específica del subsistema, la Fachada puede quedarse corta.
- Falsa simplicidad: Puede dar la sensación de que "todo es fácil" cuando por debajo hay complejidad real que hay que entender.
9. Errores comunes
1. La Fachada God Class
El error más frecuente con diferencia es meter toda la lógica del negocio en la Fachada. Si tu Fachada tiene 500 líneas y 30 métodos, ya no es un Facade, es un God Class God Class Antipatrón donde una clase acumula demasiadas responsabilidades, convirtiéndose en un monstruo difícil de mantener, testear y entender. :
// ❌ MAL: la Fachada hace TODO
class TiendaFacade {
public function realizarPedido() { /* 100 líneas */ }
public function gestionarEnvios() { /* 80 líneas */ }
public function generarInformes() { /* 60 líneas */ }
public function administrarUsuarios() { /* 90 líneas */ }
// ... 20 métodos más
}
// ✅ BIEN: varias Fachadas pequeñas
class PedidoFacade { /* Solo pedidos */ }
class EnvioFacade { /* Solo envíos */ }
class InformeFacade { /* Solo informes */ }
class UsuarioFacade { /* Solo usuarios */ }
Si tu Fachada empieza a crecer, divídela. Varias fachadas pequeñas son más fáciles de mantener que una gigante.
2. La Fachada con lógica de negocio
La Fachada debe orquestar, no implementar. Si tiene if/else, cálculos o validaciones propias, está haciendo demasiado:
// ❌ MAL: la Fachada calcula cosas
class PedidoFacade {
public function realizarPedido(float $precio, float $descuento): bool {
$precioFinal = $precio - ($precio * $descuento / 100); // ← Esto NO va aquí
$impuestos = $precioFinal * 0.21; // ← Esto tampoco
return $this->pagos->cobrar($precioFinal + $impuestos);
}
}
// ✅ BIEN: la Fachada solo delega
class PedidoFacade {
public function realizarPedido(float $precio, float $descuento): bool {
$precioFinal = $this->calculadora->aplicarDescuento($precio, $descuento);
$total = $this->calculadora->conImpuestos($precioFinal);
return $this->pagos->cobrar($total);
}
}
3. Crear dependencias con new dentro de la Fachada
Ya se ha dicho en el post, pero vale la pena repetirlo porque es un clásico. Si haces new dentro del constructor, no puedes testear ni sustituir los subsistemas:
// ❌ MAL: dependencias hardcodeadas
public function __construct() {
$this->pagos = new StripeProcessor(); // Atado a Stripe
}
// ✅ BIEN: inyección de dependencias
public function __construct(ProcesadorDePagos $pagos) {
$this->pagos = $pagos; // Cualquier procesador que cumpla la interfaz
}
4. Esconder los subsistemas completamente
El Facade no debería prohibir el acceso directo a los subsistemas. A veces el cliente necesita funcionalidad específica que la Fachada no expone, y eso está bien:
// ✅ La Fachada es un atajo, no una jaula
$pedido = new PedidoFacade($inventario, $pagos, $email);
$pedido->realizarPedido(...); // Camino fácil
// Pero si necesitas algo específico, accedes directo
$inventario->getStockDetallado('TSHIRT-001'); // Funcionalidad que la Fachada no cubre
10. ¿Cuándo usarlo y cuándo no?
- Tienes un subsistema con muchas clases que el cliente no necesita conocer
- Necesitas simplificar una operación que requiere coordinar 3+ objetos
- Quieres desacoplar tu código de una librería o API externa
- Varios sitios del código repiten la misma secuencia de llamadas
- Quieres ofrecer una API pública simple para un módulo interno complejo
- Solo tienes 1-2 clases simples (no hay complejidad que simplificar)
- El cliente necesita control total sobre los subsistemas
- La Fachada acabaría siendo un pass-through que solo reenvía llamadas sin añadir valor
- Estás creando la Fachada antes de que exista el subsistema (sobreingeniería)
Si te encuentras copiando y pegando las mismas 5 líneas de inicialización y llamadas en varios sitios, eso es un Facade pidiéndote a gritos que lo crees. Es un buen comienzo para detectar posibles implementaciones.
11. Checklist: domina el patrón Facade
Conclusión
El Patrón Facade es la capa protectora que pones entre tu código y las librerías o módulos complejos que utilizas. El objetivo es ofrecer un método bonito y limpio que por detrás orqueste todo el caos.
Lo ves en Laravel (DB::, Cache::, Mail::), lo ves cuando envuelves una API de Stripe en tu propia clase, lo ves cuando creas un DeployService que ejecuta 10 pasos con una sola llamada.
No añade funcionalidad nueva. No modifica los subsistemas, solo los coordina. Y eso, aunque suena a poca cosa, marca la diferencia entre un código que da miedo tocar y uno que da gusto leer.
EA, nos vemos en los bares 🍻
Pon a prueba lo aprendido
1. ¿Cuál es el principal objetivo del Patrón Facade?
2. ¿Qué rol cumplen las clases como ProcesadorDePagos o GestorDeInventario en el patrón?
3. ¿Por qué es mejor inyectar las dependencias en la Fachada en vez de crearlas con new?
4. ¿Cuál es la diferencia principal entre Facade y Adapter?
5. ¿Qué principio SOLID está directamente relacionado con que el cliente solo dependa de la Fachada?
6. ¿Qué es el problema de la 'God Class' en el contexto del Facade?
7. ¿La Fachada debe prohibir el acceso directo a los subsistemas?
8. ¿Cuándo NO deberías usar el patrón Facade?