Diseño de software

Diferencias entre Adapter, Facade, Proxy y Decorator

Adapter transforma interfaces, Facade oculta complejidad, Proxy controla el acceso y Decorator añade funcionalidad. Comparamos cuatro patrones de envoltorio similares por su intención y criterios de elección.

4 min de lectura
Imagen de portada de Diferencias entre Adapter, Facade, Proxy y Decorator

Los cuatro patrones de envoltorio: ¿por qué confunden tanto?

Al estudiar patrones de diseño, siempre llega un punto en el que te topas con un muro.

Adapter, Facade, Proxy y Decorator. Es fácil mezclarlos y confundirlos.

Es normal pensar: «¿Acaso no se limitan todos a envolver otro objeto?». En efecto, los cuatro contienen otro objeto y se colocan delante de él, por lo que su aspecto es similar.

Por eso mucha gente memoriza los nombres, pero luego no consigue distinguirlos en el código.

Empecemos por lo esencial.

Los cuatro patrones envuelven objetos, pero lo hacen con un «propósito» diferente.

Adapter cambia la interfaz, Facade oculta la complejidad, Proxy controla el acceso y Decorator añade funcionalidad.

Si recuerdas esta frase, lo demás encaja. En este artículo separaremos claramente a estos cuatro hermanos para que puedas distinguirlos en el código.

Si después de la comparación necesitas una implementación real, puedes continuar con Envolver una API heredada con Adapter en Swift y Simplificar un subsistema con Facade en Swift.


Tabla comparativa de los cuatro hermanos

Antes de explicarlos, veamos primero una tabla. Yo la tenía pegada frente al escritorio y la consultaba cada vez que me confundía.

Patrón Propósito Interfaz Objetivo envuelto
Adapter Adapta una interfaz incompatible Cambia Normalmente uno
Facade Ofrece una entrada sencilla a varios subsistemas complejos Crea una nueva Varios
Proxy Controla, retrasa o almacena en caché el acceso al original Igual Uno
Decorator Añade funcionalidad al original Igual Uno

El criterio más importante es si «la interfaz permanece igual».

Proxy y Decorator tienen la misma interfaz que el original, así que el cliente no necesita saber que hay un envoltorio.

En cambio, Adapter cambia intencionadamente la interfaz y Facade crea una entrada completamente nueva.

Si preguntas solo por qué se envuelve, la diferencia queda clara
Si preguntas solo por qué se envuelve, la diferencia queda clara

Adapter frente a Decorator: ¿en qué se diferencian?

Esta es la pareja que más se confunde. Al verla con código, la diferencia resulta evidente.

Adapter es un convertidor que hace compatible lo incompatible. Sí, como el adaptador que permite conectar un dispositivo de 220 V a un enchufe de 110 V.

// La biblioteca existente solo tiene legacyPrint(text:)
// Cuando nuestro código espera draw()
protocol Renderer { func draw() }

struct LegacyLabel { func legacyPrint(_ t: String) { print(t) } }

struct LabelAdapter: Renderer {
    let legacy: LegacyLabel
    func draw() { legacy.legacyPrint("Llamada convertida") }
}

LabelAdapter(legacy: LegacyLabel()).draw()
// Salida: llamada convertida

La clave es que la interfaz cambia de legacyPrint a draw.

Decorator mantiene la interfaz y añade funcionalidad, como agregar un shot al café.

protocol Coffee { func cost() -> Int }

struct Americano: Coffee { func cost() -> Int { 4000 } }

struct ShotDecorator: Coffee {
    let base: Coffee
    func cost() -> Int { base.cost() + 500 }
}

ShotDecorator(base: Americano()).cost()
// Salida: 4500

Ambos contienen un base, pero Adapter cambia nombres y Decorator amplía el comportamiento. Su propósito es completamente distinto.


¿Y Proxy frente a Facade?

Proxy tiene exactamente la misma interfaz que el original, pero controla el acceso desde el medio.

Con la carga de imágenes, no carga la imagen real inmediatamente; espera hasta que sea necesaria. Eso es lazy loading.

El almacenamiento en caché, las comprobaciones de permisos y el registro también son tareas habituales de Proxy. El cliente cree llamar al original, pero en realidad llama a un sustituto.

Facade es algo diferente. No envuelve uno, sino que oculta varios objetos detrás.

En un cine en casa, reúne encender el proyector, encender los altavoces, atenuar las luces e iniciar la reproducción en una sola llamada a watchMovie(). Así se puede usar con un botón sin conocer los detalles internos.

Cuando me confundía, pegaba esta nota en el monitor
Cuando me confundía, pegaba esta nota en el monitor

En resumen, Proxy es «el guardián de la misma puerta» y Facade es «el mostrador que abre varias puertas por ti».


Cuándo usarlos y cuándo evitarlos

Los patrones son herramientas: úsalos según la situación. Forzarlos solo hace que el código sea más complejo.

Situación Elección
La interfaz de una biblioteca externa no encaja Adapter
Quieres una entrada sencilla para varios módulos complejos Facade
Necesitas control de acceso, lazy loading o caché Proxy
Quieres combinar y añadir funcionalidades con flexibilidad Decorator

También hay casos claros en los que conviene evitarlos.

  • Si no hay motivo para envolver algo, añadir un patrón solo por decir que lo has usado únicamente suma capas.
  • Si apilas demasiados Decorator, depurar se convierte en un infierno: ya no sabes dónde cambió un valor.
  • Si Facade asume demasiado, acaba convirtiéndose en un bloque enorme.

Me pregunto: «¿Cuál de los cuatro propósitos justifica este envoltorio?». Si no encuentro respuesta, elimino el patrón.

Así se pregunta en una entrevista

P. Proxy y Decorator envuelven objetos con la misma interfaz. ¿Cuál es la diferencia?

R. Su propósito. Proxy controla, retrasa o almacena en caché el acceso al original, pero mantiene intacta su funcionalidad. Decorator conserva la interfaz original y añade funcionalidad. Proxy decide «si llamar» y Decorator decide «qué añadir después de llamar».

P. ¿Cuál es la diferencia entre Adapter y Facade?

R. Adapter suele envolver un único objetivo para adaptar una interfaz incompatible. Facade envuelve varios subsistemas y ofrece una nueva entrada sencilla. Adapter «traduce» la interfaz y Facade la «resume».


Conclusión

La diferencia entre los cuatro hermanos se reduce a una pregunta: «¿Por qué lo envuelves?». ¿Para cambiar, ocultar, controlar o añadir algo a la interfaz?

Con esta pregunta dejarás de confundirte frente al código. Guarda la tabla comparativa de hoy y consúltala cuando la necesites.

Para seguir leyendo