Patrón Adapter en C#: Guía Completa con Ejemplos

Introducción: Traductor entre mundos

El Patrón Adapter es como un traductor simultáneo: permite que dos sistemas que hablan idiomas distintos puedan comunicarse sin que ninguno cambie su forma de hablar.

En software, esto ocurre cuando quieres usar una librería antigua o un servicio externo con una interfaz incompatible. En vez de reescribirlo todo, creas un adaptador que traduce llamadas de un formato a otro.

Este patrón es uno de los más prácticos porque aparece en integraciones reales: APIs legacy, SDKs de terceros, dispositivos externos, etc.

Conexión entre dos interfaces incompatibles mediante un adaptador, simbolizando el Patrón Adapter.
Prompt: Two mismatched plugs connected by a sleek adapter, minimal studio lighting, high-detail product style.

1. La Naturaleza: El Pico del Colibrí

El colibrí tiene un pico largo y fino diseñado para acceder a néctar en flores profundas. La flor, por su parte, tiene una forma específica que “espera” ese tipo de pico.

En este escenario, el colibrí funciona como un adaptador biológico entre la flor y la necesidad de alimento. Si otro pájaro con pico corto quisiera acceder al néctar, necesitaría un “adaptador” (otra estrategia) o no podría alimentarse.

La clave: ni la flor ni el colibrí cambian su forma. El “adaptador” ya está en el diseño del pico.

Colibrí alimentándose de una flor profunda, analogía natural del Patrón Adapter.
Prompt: Hummingbird feeding from deep tubular flower, soft sunlight, nature documentary style.

2. Mundo Real: Enchufes y Adaptadores

Viajas a otro país y descubres que tu cargador no encaja en el enchufe. El problema no es tu cargador, ni el enchufe: la interfaz es incompatible.

La solución es un adaptador físico que convierte el formato del cargador al formato del enchufe. Ese adaptador no cambia el cargador ni el enchufe, solo actúa como traductor.

Adaptador de enchufe internacional conectando dispositivos de distintos estándares.
Prompt: Travel plug adapter connecting US charger to EU socket, clean white background, product photography.

3. Implementación en C#: Código Paso a Paso

Imaginemos que tenemos un sistema moderno que espera una interfaz IPago, pero queremos usar una librería legacy que trabaja con PagoLegacy.

3.1 La interfaz esperada (Target)

public interface IPago
{
    void Pagar(decimal monto);
}

3.2 La clase legacy (Adaptee)

// Librería antigua que NO podemos modificar
public class PagoLegacy
{
    public void EjecutarPago(double cantidad)
    {
        Console.WriteLine($"[Legacy] Pago ejecutado por {cantidad}€");
    }
}

3.3 El Adaptador

// Adaptador que convierte IPago en PagoLegacy
public class PagoAdapter : IPago
{
    private readonly PagoLegacy _legacy;

    public PagoAdapter(PagoLegacy legacy)
    {
        _legacy = legacy;
    }

    public void Pagar(decimal monto)
    {
        // Adaptamos decimal a double y delegamos
        _legacy.EjecutarPago((double)monto);
    }
}

3.4 Uso en el sistema moderno

public class Checkout
{
    private readonly IPago _pago;

    public Checkout(IPago pago)
    {
        _pago = pago;
    }

    public void ProcesarCompra(decimal total)
    {
        Console.WriteLine($"Procesando compra por {total}€...");
        _pago.Pagar(total);
    }
}

// Uso
var legacy = new PagoLegacy();
var adapter = new PagoAdapter(legacy);
var checkout = new Checkout(adapter);

checkout.ProcesarCompra(99.99m);

Resultado: El sistema moderno usa su interfaz IPago sin saber que internamente se está usando una librería antigua.

4. Adapter vs Facade vs Bridge

  • Adapter: Traduce una interfaz a otra para hacer sistemas compatibles.
  • Facade: Simplifica un conjunto de subsistemas complejos con una interfaz más simple.
  • Bridge: Separa abstracción de implementación desde el diseño.

Si tu problema es compatibilidad, usa Adapter. Si tu problema es complejidad, usa Facade. Si tu problema es explosión combinatoria de jerarquías, usa Bridge.

Comparativa visual entre Adapter, Facade y Bridge.
Prompt: Three-panel infographic comparing Adapter, Facade, Bridge; clean vector UI, neutral colors.

5. Diagrama UML y Definición Formal

Diagrama UML del Patrón Adapter con Target, Adapter y Adaptee.
Prompt: UML class diagram of Adapter pattern, minimalist, black and blue vector style.
Es un patrón estructural que convierte la interfaz de una clase en otra que el cliente espera. Permite que clases incompatibles trabajen juntas.

⚠️ Cuándo NO Usar el Patrón Adapter

  • Si puedes cambiar directamente la clase original, no necesitas adapter.
  • Si solo tienes una pequeña diferencia, quizá sea mejor usar una función simple.
  • Si la adaptación es demasiado compleja, puede esconder problemas de diseño.

💪 Ejercicio para Practicar

Implementa un adaptador para un sistema de envío:

  1. Crea una interfaz IEnvio con Enviar(string destino).
  2. Simula una clase legacy CorreoAntiguo con método EnviarPaquete(string direccion).
  3. Crea un CorreoAdapter que implemente IEnvio y traduzca la llamada.

Conclusión: Compatibilidad sin dolor

Adapter es el patrón que hace posible integrar lo viejo con lo nuevo sin romper nada. Es una forma elegante de mantener compatibilidad y evitar reescribir sistemas completos.

Cuando veas una API legacy, no pienses en reemplazarla de inmediato: piensa en adaptarla.