Menu
Coddy logo textTech

Patrón Adapter

Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy. Lección 92 de 107.

El patrón Adapter permite que interfaces incompatibles trabajen juntas al envolver un tipo existente con una interfaz nueva. Mientras que Command encapsula acciones, Adapter traduce una interfaz a otra que los clientes esperan.

Imagina que tienes una impresora heredada que utiliza una firma de método diferente de la que espera tu aplicación:

// Interfaz objetivo que utiliza tu aplicación
type Printer interface {
    Print(text string) string
}

// Impresora heredada con interfaz incompatible
type OldPrinter struct{}

func (o OldPrinter) PrintDocument(doc string, copies int) string {
    return fmt.Sprintf("Old printer: %s (x%d)", doc, copies)
}

El adaptador envuelve el tipo heredado e implementa la interfaz esperada:

type OldPrinterAdapter struct {
    oldPrinter OldPrinter
}

func (a OldPrinterAdapter) Print(text string) string {
    return a.oldPrinter.PrintDocument(text, 1)
}

Ahora la impresora heredada funciona sin problemas con el código que espera la interfaz Printer:

func PrintMessage(p Printer, msg string) string {
    return p.Print(msg)
}

adapter := OldPrinterAdapter{oldPrinter: OldPrinter{}}
result := PrintMessage(adapter, "Hello")  // "Old printer: Hello (x1)"

El patrón Adapter es invaluable al integrar bibliotecas de terceros, trabajar con código heredado o cuando necesitas usar clases existentes que no coinciden con los requisitos de tu interfaz. Actúa como un puente sin modificar el código original.

challenge icon

Desafío

Fácil

¡Construyamos un sistema de reproducción multimedia usando el patrón Adaptador! Tienes un reproductor de audio moderno que espera una interfaz unificada, pero necesitas integrar equipos de audio heredados que utilizan firmas de métodos completamente diferentes. Tu adaptador cubrirá esta brecha, permitiendo que el hardware antiguo funcione sin problemas con el nuevo sistema.

Organizarás tu código en tres archivos:

  • player.go: Define tu interfaz objetivo y un dispositivo de audio heredado.

    Crea una interfaz AudioPlayer que tu sistema moderno espera, con un método Play(track string) string que recibe el nombre de una pista y devuelve un mensaje de reproducción.

    Define también un dispositivo heredado que no coincide con esta interfaz:

    • Estructura VinylPlayer con un campo SpeedRPM (int). Tiene un método DropNeedle(record string, side string) string que devuelve Playing [record] ([side] side) at [speed]rpm

    La interfaz de VinylPlayer es incompatible con AudioPlayer. Requiere dos parámetros y utiliza un nombre de método completamente diferente.

  • adapter.go: Crea tu adaptador para hacer compatible el dispositivo heredado.

    Construye una estructura VinylAdapter que envuelva un VinylPlayer e implemente la interfaz AudioPlayer. Cuando se llame a Play, el adaptador debe llamar al método DropNeedle del reproductor de vinilos, usando A como valor predeterminado para el parámetro del lado.

    Crea también un reproductor moderno para compararlo:

    • Estructura DigitalPlayer: su método Play devuelve Streaming: [track]
  • main.go: Demuestra el funcionamiento de ambos reproductores mediante la misma interfaz.

    Crea una función PlayMusic(player AudioPlayer, track string) string que utilice la interfaz para reproducir música. Esta función no debería saber ni preocuparse por si está utilizando un reproductor digital o un reproductor de vinilos adaptado.

    Lee el tipo de reproductor (digital o vinyl) y, si es vinyl, lee también la velocidad en RPM. Después, lee el nombre de la pista. Crea el reproductor apropiado (usando el adaptador para vinyl), reproduce la pista mediante tu función PlayMusic e imprime el resultado.

Se proporcionarán las siguientes entradas:

  • Línea 1: Tipo de reproductor (digital o vinyl)
  • Línea 2: Velocidad en RPM (solo si es vinyl)
  • Última línea: Nombre de la pista que se reproducirá

Por ejemplo, dada la siguiente entrada:

digital
Bohemian Rhapsody

La salida debería ser:

Streaming: Bohemian Rhapsody

Y dada la siguiente entrada:

vinyl
33
Abbey Road

La salida debería ser:

Playing Abbey Road (A side) at 33rpm

Y dada la siguiente entrada:

vinyl
45
Blue Monday

La salida debería ser:

Playing Blue Monday (A side) at 45rpm

Observa cómo la función PlayMusic funciona de forma idéntica con ambos reproductores. No sabe que el reproductor de vinilos en realidad está siendo adaptado desde una interfaz completamente diferente. ¡El adaptador traduce las llamadas a la interfaz moderna al formato heredado entre bastidores!

Pruébalo tú mismo

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

// PlayMusic usa la interfaz AudioPlayer para reproducir música
// Esta función funciona con cualquier implementación de AudioPlayer
// TODO: Implementa esta función para llamar a player.Play(track) y devolver el resultado
func PlayMusic(player AudioPlayer, track string) string {
	// TODO: Implementa esta función
	return ""
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// Leer el tipo de reproductor
	playerType, _ := reader.ReadString('\n')
	playerType = strings.TrimSpace(playerType)
	
	var player AudioPlayer
	var track string
	
	if playerType == "vinyl" {
		// Leer la velocidad RPM para vinilo
		rpmStr, _ := reader.ReadString('\n')
		rpmStr = strings.TrimSpace(rpmStr)
		rpm, _ := strconv.Atoi(rpmStr)
		
		// Leer el nombre de la pista
		track, _ = reader.ReadString('\n')
		track = strings.TrimSpace(track)
		
		// TODO: Crea un VinylPlayer con el RPM dado
		// TODO: Envuélvelo en un VinylAdapter
		// TODO: Asígnarlo a la variable player
		_ = rpm // Elimina esta línea cuando uses rpm
	} else {
		// Leer el nombre de la pista
		track, _ = reader.ReadString('\n')
		track = strings.TrimSpace(track)
		
		// TODO: Crea un DigitalPlayer
		// TODO: Asígnarlo a la variable player
	}
	
	// TODO: Llama a PlayMusic e imprime el resultado
	_ = player // Elimina esta línea cuando uses player
	_ = track  // Elimina esta línea cuando uses track
}
quiz iconPonte a prueba

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

Practica por tu cuenta: Compilador de Go online