🚨 ¡Nueva review! 🔇 Los mejores cascos con ANC del mercado: los Sony WH-1000XM4 . ¡Échale un ojo! 👀

El Patrón de diseño Bridge

Desacopla la Abstracción de la Implementación. ¡Construye puentes!

Escrito por domin el 5 de noviembre de 2025

🌉 El Patrón Bridge: El Arquitecto de la Flexibilidad

El Patrón de diseño Bridge tiene un objetivo que parece complejo, pero es superútil: desacoplar una abstracción de su implementación, de forma de que ambas puedan variar o evolucionar de forma independiente.

Imagina que tienes dos “dimensiones” de cambio en tu código, por ejemplo:

  1. Tipos de Notificación (SMS, Email, Push).
  2. Contenidos de la Notificación (Advertencia, Informativa, Urgente).

Si no usas el patrón Bridge terminarías con una matriz de clases: SmsAdvertencia, EmailAdvertencia, SmsInformativa, etc. El número de clases creadas te acabaría devorando.

El Patrón Bridge resuelve esto: crea un “puente” que conecta la parte de qué es (la Abstracción, ej. Mensaje de Advertencia) con la parte de cómo se hace (la Implementación, ej. Enviar por Email), sin que se “conozcan” directamente.

🌉 1. Un ejemplo sencillo: El mando a distancia universal

Imagina que tienes varios dispositivos electrónicos (TV, Radio, Proyector) y quieres controlarlos con un Mando a Distancia Universal.

De esta forma, puedes crear un nuevo Mando (ej. un Mando con Voz) sin tocar los Dispositivos (TV, Radio), y puedes crear un nuevo Dispositivo (ej. Proyector Laser) sin tocar los Mandos existentes porque funcionan por separado.

Concepto (Analogía)

Rol en Bridge

Tarea Principal

Mando a Distancia Universal

Abstracción

Define la lógica de alto nivel (el “qué”). Contiene la referencia a la Implementación.

Interfaz del Dispositivo (e.g. iDispositivo)

Implementador (Interfaz)

Define la interfaz de las operaciones de bajo nivel (el “cómo”).

TV, Radio, Proyector

Implementación Concreta

Contiene la lógica específica de cómo se hacen las cosas para cada plataforma/clase.

El truco está en que la Abstracción solo conoce la Interfaz del Implementador y no las Implementaciones concretas, esto es el puente.

🛠️ 2. Los tres pilares del patrón Bridge

El patrón Bridge necesita estos roles para funcionar correctamente:

1. La Interfaz del Implementador (El “Cómo”)

2. La Implementación Concreta (El “Cómo Específico”)

3. La Abstracción (El “Qué”)

4. La Abstracción Refinada (El “Qué Específico”)

🤔 1. ¿Cuál es el objetivo principal del Patrón Bridge?

✉️ 3. El ejemplo clásico: Mensajes y Canales de Envío

Imagina que tienes diferentes tipos de mensajes (simples, advertencias) y diferentes canales para enviarlos (Email, SMS). Queremos que la forma en que se prepara el mensaje sea independiente del canal que lo envía.

Clase/Rol

Función (Ej. enviarMensaje)

Abstracción Refinada

Define la forma del mensaje (Ej. añadir el prefijo “ALERTA: ”). Llama al método send() de su Implementación.

Implementación Concreta

Contiene la lógica de bajo nivel para enviarPorEmail(...) o enviarPorSMS(...).

El cliente simplemente instancia el tipo de mensaje que quiere (SimpleMessage) y le pasa la forma en que quiere que se envíe (EmailSender).
El cliente construye el puente en tiempo de ejecución

🤔 2. En el Patrón Bridge, ¿qué rol 'contiene' la referencia al Implementador (el 'cómo')?

✅ 4. ¿Por Qué Usarlo?

El patrón de diseño Bridge es la herramienta de la arquitectura de software cuando necesitas una flexibilidad máxima en dos ejes:

  1. Elimina el Producto Cartesiano: Evita que el número de clases crezca exponencialmente (evita tener que crear SmsAdvertencia, EmailAdvertencia, etc.). En su lugar, tienes N abstracciones y M implementaciones, y las combinas (N + M clases).
  2. Modularidad y Escalabilidad: Puedes añadir un nuevo canal de envío (ej. WhatsappSender) sin tocar ninguna de las clases de tipo de mensaje. O puedes crear un nuevo tipo de mensaje (GreetingsMessage) sin tocar los canales de envío.
  3. Encapsulamiento: La lógica de alto nivel (la Abstracción) no necesita conocer los detalles sucios de cómo se ejecuta la acción (la Implementación).

❌ 5. Desventaja a Considerar

🤔 3. Si queremos añadir un nuevo tipo de notificación (ej. WhatsApp) al sistema, ¿qué parte del Bridge Pattern tocaríamos?

💡 6. Conclusión

El Patrón Bridge te permite construir sistemas donde los componentes de alto nivel (la lógica de negocio o “qué”) no están atados a los componentes de bajo nivel (la plataforma o el “cómo”). Es la clave para crear software verdaderamente flexible y escalable, donde añadir una nueva funcionalidad en un eje no rompe ni exige cambios en el otro eje.

🧠 7. Ejemplo Práctico en PHP

Vamos a implementar el patrón Bridge con el ejemplo de un sistema de mensajes que puede enviar notificaciones con distintos contenidos por distintos canales (Email, SMS).

<?php

// 🔹 1. La Interfaz del Implementador (El contrato del 'cómo' se envía)
interface SenderInterface {
    public function send(string $subject, string $body): void;
}

// 🔹 2. Implementaciones Concretas (El 'cómo' específico)
class EmailSender implements SenderInterface {
    public function send(string $subject, string $body): void {
        echo "[EMAIL SENDER] Enviando..." . PHP_EOL;
        echo "   ASUNTO: $subject" . PHP_EOL;
        echo "   CUERPO: $body" . PHP_EOL;
    }
}

class SmsSender implements SenderInterface {
    public function send(string $subject, string $body): void {
        // En SMS el 'subject' se ignora o se une al cuerpo.
        echo "[SMS SENDER] Enviando al móvil: $subject - $body (Máx. 160 chars)" . PHP_EOL;
    }
}

// 🔹 3. La Abstracción (La lógica de 'qué' se prepara, contiene el puente)
abstract class Message {
    // La Abstracción guarda la referencia a la Implementación (El Puente)
    protected SenderInterface $sender;
    protected string $content;

    public function __construct(SenderInterface $sender, string $content) {
        $this->sender = $sender;
        $this->content = $content;
    }

    // Método que las Abstracciones Refinadas deben implementar
    abstract public function send(): void;
}

// 🔹 4. Abstracciones Refinadas (El 'qué' específico)
class SimpleMessage extends Message {
    public function send(): void {
        $this->sender->send("Mensaje Simple", $this->content);
    }
}

class WarningMessage extends Message {
    public function send(): void {
        $subject = "⚠️ ALERTA: Acceso Ilegal Detectado";
        $body = "Por favor, revisa: " . $this->content;
        $this->sender->send($subject, $body);
    }
}

// 5. Uso del patrón (El Cliente)
// ---------------------------------------------------------------------

$emailSender = new EmailSender();
$smsSender = new SmsSender();

// Se crea un "Mensaje Simple" enviado por Email
$simpleEmail = new SimpleMessage($emailSender, "Tu pedido 456 ha sido enviado.");
$simpleEmail->send();

echo PHP_EOL;

// Se crea un "Mensaje de Advertencia" enviado por SMS
$warningSms = new WarningMessage($smsSender, "Intento de login fallido desde IP sospechosa.");
$warningSms->send();

// ---------------------------------------------------------------------

// 🖥️ Salida del programa:
// [EMAIL SENDER] Enviando...
//    ASUNTO: Mensaje Simple
//    CUERPO: Tu pedido 456 ha sido enviado.
//
// [SMS SENDER] Enviando al móvil: ⚠️ ALERTA: Acceso Ilegal Detectado
// Por favor, revisa: Intento de login fallido desde IP sospechosa.

Diferenciando Abstracción vs. Implementación

En este ejemplo, la Abstracción (las clases Message, como SimpleMessage) se encarga de lo que es el mensaje (Ej. si es simple o de advertencia), mientras que la Implementación (las clases Sender) se encarga del canal (Email, SMS). El Bridge conecta “Mensaje de Advertencia” con “Enviar por SMS” de forma transparente para el cliente.

EA pues eso es todo, ¡saluditos y nos vemos en los bares! 🍻