Patrón Adapter
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy. Lección 76 de 91.
El patrón Adaptador es un patrón de diseño estructural que permite que objetos con interfaces incompatibles trabajen juntos. Actúa como un puente entre dos interfaces, traduciendo las llamadas de un formato a otro.
Imagina que estás creando una aplicación que procesa pagos y necesitas integrar una biblioteca de pagos de terceros. La biblioteca funciona perfectamente, pero su interfaz no coincide con lo que espera tu código. En lugar de reescribir toda tu aplicación, creas un adaptador que traduce entre ambos.
<?php
// La interfaz que espera tu aplicación
interface PaymentProcessor {
public function pay(float $amount): string;
}
// Biblioteca de terceros con una interfaz diferente
class StripeAPI {
public function createCharge(int $cents, string $currency): string {
return "Charged {$cents} {$currency} via Stripe";
}
}
El adaptador implementa la interfaz esperada mientras utiliza internamente la clase de terceros:
<?php
class StripeAdapter implements PaymentProcessor {
public function __construct(private StripeAPI $stripe) {}
public function pay(float $amount): string {
$cents = (int)($amount * 100);
return $this->stripe->createCharge($cents, 'USD');
}
}
$stripe = new StripeAPI();
$processor = new StripeAdapter($stripe);
echo $processor->pay(29.99);
Salida:
Charged 2999 USD via StripeEl adaptador convierte los dólares en centavos y llama al método correspondiente. El código de tu aplicación solo conoce PaymentProcessor, sin preocuparse por los requisitos específicos de Stripe. Si más adelante cambias a otro proveedor de pagos, simplemente creas un adaptador nuevo sin modificar el código existente.
Desafío
FácilConstruyamos un sistema de conversión de temperatura utilizando el patrón Adapter. Tienes un sensor de temperatura heredado que proporciona lecturas en Fahrenheit, pero tu aplicación meteorológica moderna espera todas las temperaturas en Celsius. En lugar de modificar cualquiera de los dos sistemas, crearás un adaptador que conecte ambos.
Organizarás tu código en cuatro archivos:
TemperatureSensor.php: Define una interfazTemperatureSensorque tu aplicación meteorológica espera. Debe tener un métodogetTemperature(): floatque devuelva la temperatura en Celsius.LegacySensor.php: Crea una claseLegacySensorque simule el hardware antiguo. Esta clase tiene una interfaz diferente de la que necesita tu aplicación:- Recibe una lectura en Fahrenheit en su constructor (utiliza la promoción de constructor)
- Tiene un método
readFahrenheit(): floatque devuelve el valor Fahrenheit almacenado
LegacySensorAdapter.php: Incluye tanto la interfaz TemperatureSensor como la clase LegacySensor. Crea una claseLegacySensorAdapterque implementeTemperatureSensory envuelva unLegacySensor. Tu adaptador debe:- Aceptar un
LegacySensoren su constructor - Implementar
getTemperature()leyendo el valor Fahrenheit del sensor heredado y convirtiéndolo a Celsius mediante la fórmula:(fahrenheit - 32) * 5 / 9
- Aceptar un
main.php: Incluye el archivo LegacySensorAdapter. Recibirás una entrada: una temperatura en Fahrenheit.Crea un
LegacySensorcon la temperatura de entrada y, después, envuélvelo en unLegacySensorAdapter. Llama agetTemperature()en el adaptador e imprime el resultado redondeado a dos decimales.El formato de salida debe ser:
Temperature: [celsius]C
Este desafío demuestra cómo el patrón Adapter permite integrar interfaces incompatibles sin modificar el código existente. Tu aplicación meteorológica trabaja exclusivamente con la interfaz TemperatureSensor, sin saber que las lecturas reales provienen de un sensor Fahrenheit heredado.
Pruébalo tú mismo
<?php
require_once 'LegacySensorAdapter.php';
// Leer entrada
$fahrenheit = floatval(trim(fgets(STDIN)));
// TODO: Crea un LegacySensor con la temperatura de entrada
// TODO: Envuélvelo en un LegacySensorAdapter
// TODO: Llama a getTemperature() en el adaptador
// TODO: Imprime el resultado redondeado a dos decimales
// Formato de salida: Temperature: [celsius]C
?>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 la POO
Archivos externosIntroducción a la POOClases frente a objetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Repaso: calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasRepaso - Jerarquía de empleados7Encapsulación
Público, protegido, privadoModificadores de acceso en profundidadGetters y settersOcultación de la informaciónPromoción del constructor (8.0)Repaso: sistema de registros de estudiantes10Conceptos avanzados de OOP
Composición vs. herenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibras (PHP 8.1)Análisis profundo de la clonación de objetosGeneradores e iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Namespaces y carga automática
Introducción a los NamespacesLa palabra clave useEstándar de carga automática PSR-4Autoloader de ComposerRepaso: proyecto organizado5Interfaces y contratos
Introducción a las interfacesImplementación de interfacesImplementación de múltiples interfacesInterfaces vs. clase abstractaTipado con interfacesRepaso - Calculadora de formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeRepaso: colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Repaso: gestor de cuentas bancarias6Polimorfismo
Repaso de la sobrescritura de métodosPolimorfismo mediante interfacesAnotaciones de tipo y tipos uniónEnlace estático tardíoRepaso: procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos entre TraitsMétodos abstractos en TraitsTraits frente a la herencia12Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón StrategyPractica por tu cuenta: Compilador de PHP online