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.
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.
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.
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.
Prompt: Three-panel infographic comparing Adapter, Facade, Bridge; clean vector UI, neutral colors.
5. Diagrama UML y Definición Formal
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:
- Crea una interfaz
IEnvioconEnviar(string destino). - Simula una clase legacy
CorreoAntiguocon métodoEnviarPaquete(string direccion). - Crea un
CorreoAdapterque implementeIEnvioy 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.