Patrón Adapter
Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy. Lección 57 de 70.
El patrón Adapter es un patrón estructural que permite que interfaces incompatibles trabajen juntas. Actúa como un puente entre dos clases, convirtiendo la interfaz de una clase en una interfaz que los clientes esperan. Piensa en él como un adaptador de corriente que te permite conectar un dispositivo europeo a un enchufe estadounidense.
Este patrón es particularmente útil cuando quieres usar una clase existente pero su interfaz no coincide con lo que tu código necesita. En lugar de modificar la clase original (la cual podrías no controlar), creas un adaptador que la envuelve:
// Clase existente con interfaz incompatible
public class OldPrinter
{
public void PrintMessage(string msg) => Console.WriteLine($"Old: {msg}");
}
// Interfaz que su código espera
public interface IPrinter
{
void Print(string text);
}
// El adaptador cierra la brecha
public class PrinterAdapter : IPrinter
{
private OldPrinter _oldPrinter;
public PrinterAdapter(OldPrinter oldPrinter)
{
_oldPrinter = oldPrinter;
}
public void Print(string text)
{
_oldPrinter.PrintMessage(text); // Delega a la interfaz antigua
}
}Ahora su código puede funcionar con la impresora antigua a través de la interfaz esperada:
OldPrinter legacy = new OldPrinter();
IPrinter printer = new PrinterAdapter(legacy);
printer.Print("Hello"); // Anterior: HelloEl patrón Adapter es invaluable al integrar bibliotecas de terceros o código heredado en tu aplicación. El código del cliente funciona con la interfaz IPrinter, completamente ajeno a que una clase antigua e incompatible realiza el trabajo real entre bastidores.
Desafío
FácilConstruyamos un sistema de reproducción multimedia usando el patrón Adapter. Tienes una biblioteca de audio existente que reproduce archivos MP3, pero tu aplicación necesita una interfaz unificada que pueda gestionar distintos tipos de medios. Crearás un adaptador para conectar esta brecha, permitiendo que tu reproductor multimedia moderno funcione sin problemas con la biblioteca de audio heredada.
Organizarás tu código en tres archivos:
LegacyAudio.cs: Representa una biblioteca existente que no puedes modificar. Crea una claseLegacyAudioPlayeren el espacio de nombresMediaSystemcon un métodoPlayMp3(string filename)que devuelva la cadena"Playing MP3: {filename}". Este es tu "adaptee": la clase con la interfaz incompatible.MediaAdapter.cs: Crea la interfaz y el adaptador en el mismo espacio de nombres. Define una interfazIMediaPlayercon un métodoPlay(string filename)que devuelva una cadena. Después, crea una claseMediaPlayerAdapterque implementeIMediaPlayer. Tu adaptador debe envolver una instancia deLegacyAudioPlayer(pasada mediante el constructor) y traducir la llamada aPlayen una llamada al métodoPlayMp3del reproductor heredado.Program.cs: Reúne todo creando el reproductor heredado, envolviéndolo en tu adaptador y usando el adaptador mediante la interfazIMediaPlayer. Esto demuestra cómo el código cliente puede trabajar con la interfaz moderna mientras el adaptador gestiona la comunicación con el sistema heredado entre bastidores.
Recibirás una entrada:
- El nombre del archivo que se reproducirá (por ejemplo,
song.mp3)
Crea un LegacyAudioPlayer, envuélvelo en un MediaPlayerAdapter, después llama a Play en el adaptador usando la interfaz IMediaPlayer e imprime el resultado.
Por ejemplo, si la entrada es favorite_track.mp3, la salida debería ser:
Playing MP3: favorite_track.mp3La ventaja de este patrón es que tu código principal solo interactúa con IMediaPlayer: no sabe que una biblioteca de audio heredada está realizando el trabajo real. Si más adelante necesitas admitir una biblioteca heredada diferente, simplemente crearías un adaptador nuevo sin cambiar ningún código cliente.
Pruébalo tú mismo
using System;
using MediaSystem;
class Program
{
public static void Main(string[] args)
{
// Lee la entrada del nombre de archivo
string filename = Console.ReadLine();
// TODO: Crea una instancia de LegacyAudioPlayer
// TODO: Envuélvelo en un MediaPlayerAdapter
// TODO: Usa el adaptador a través de la interfaz IMediaPlayer
// e imprime el resultado de llamar a Play con el nombre de archivo
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosNamespaces y directivasIntro a clases y objetosLa palabra clave 'this'Métodos y parámetrosCampos vs PropiedadesConstructoresInicializadores de objetosResumen - Calculadora simple4Herencia
Sintaxis básica de herencia (:)La palabra clave 'base'Palabras clave Virtual y OverrideClases selladas (Sealed)La clase base 'object'Resumen: Jerarquía de empleados7Características avanzadas
Sobrecarga de operadoresIndexadores (this[])Sobrescritura de ToString()Métodos de extensiónResumen - Lista personalizada10Patrones de diseño - Parte 1
Introducción a los patrones de diseñoSingleton Thread-SafePatrón FactoryPatrón Observer (Eventos)Patrón Strategy2Propiedades y miembros estáticos
Propiedades autoimplementadasPropiedades de solo lectura y escrituraCampos y métodos estáticosClases estáticasMiembros con cuerpo de expresión5Polimorfismo e Interfaces
Polimorfismo: Compilación vs. EjecuciónInterfaz vs. Clase AbstractaInterfaces MúltiplesInterfaces ExplícitasUpcasting y DowncastingRepaso: Calculadora de Figuras8Conceptos avanzados de POO
Composición sobre herenciaGenéricos (clases y métodos)Delegados y eventosAtributos y ReflexiónIDisposable y la sentencia usingFundamentos de Inyección de dependencias11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Arquitectura de clases
Datos de instancia vs. estáticosPalabras clave 'readonly' y 'const'Campos de respaldoResumen - Gestor de cuentas bancarias6Encapsulamiento
Modificadores de accesoPropiedades para el encapsulamientoImplementación de ocultamiento de datosPatrones de inmutabilidadRepaso - Registros de estudiantesPractica por tu cuenta: Compilador de C# online