Menu
Coddy logo textTech

Pattern Adapter

Fa parte della sezione Programmazione orientata agli oggetti del percorso GO di Coddy. Lezione 92 di 107.

Il pattern Adapter permette a interfacce incompatibili di collaborare avvolgendo un tipo esistente con una nuova interfaccia. Mentre Command incapsula le azioni, Adapter traduce un'interfaccia in un'altra, come si aspettano i client.

Immagina di avere una stampante legacy che utilizza una firma di metodo diversa da quella prevista dalla tua applicazione:

// Interfaccia di destinazione utilizzata dalla tua applicazione
type Printer interface {
    Print(text string) string
}

// Stampante legacy con un'interfaccia incompatibile
type OldPrinter struct{}

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

L’adattatore avvolge il tipo legacy e implementa l’interfaccia prevista:

type OldPrinterAdapter struct {
    oldPrinter OldPrinter
}

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

Ora la stampante legacy funziona senza problemi con il codice che si aspetta l'interfaccia Printer:

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

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

Il pattern Adapter è prezioso quando integri librerie di terze parti, lavori con codice legacy o hai bisogno di usare classi esistenti che non corrispondono ai requisiti della tua interfaccia. Funge da ponte senza modificare il codice originale.

challenge icon

Sfida

Facile

Costruiamo un sistema di riproduzione multimediale usando il pattern Adapter! Hai un lettore audio moderno che si aspetta un'interfaccia unificata, ma devi integrare apparecchiature audio legacy che utilizzano firme dei metodi completamente diverse. Il tuo adapter colmerà questa lacuna, permettendo al vecchio hardware di funzionare senza problemi con il nuovo sistema.

Organizzerai il codice in tre file:

  • player.go: definisci l'interfaccia di destinazione e un dispositivo audio legacy.

    Crea un'interfaccia AudioPlayer che il tuo sistema moderno si aspetta, con un metodo Play(track string) string che accetta il nome di una traccia e restituisce un messaggio di riproduzione.

    Definisci anche un dispositivo legacy che non corrisponde a questa interfaccia:

    • struct VinylPlayer con un campo SpeedRPM (int). Ha un metodo DropNeedle(record string, side string) string che restituisce Playing [record] ([side] side) at [speed]rpm

    L'interfaccia di VinylPlayer è incompatibile con AudioPlayer. Richiede due parametri e usa un nome di metodo completamente diverso.

  • adapter.go: crea il tuo adapter per rendere compatibile il dispositivo legacy.

    Crea uno struct VinylAdapter che racchiude un VinylPlayer e implementa l'interfaccia AudioPlayer. Quando viene chiamato Play, l'adapter dovrebbe chiamare il metodo DropNeedle del lettore vinile, usando A come valore predefinito per il parametro side.

    Crea anche un lettore moderno per fare un confronto:

    • struct DigitalPlayer: il suo metodo Play restituisce Streaming: [track]
  • main.go: dimostra che entrambi i lettori funzionano tramite la stessa interfaccia.

    Crea una funzione PlayMusic(player AudioPlayer, track string) string che usa l'interfaccia per riprodurre musica. Questa funzione non dovrebbe sapere né preoccuparsi se sta usando un lettore digitale o un lettore vinile adattato.

    Leggi il tipo di lettore (digital o vinyl) e, se è vinile, leggi anche la velocità RPM. Poi leggi il nome della traccia. Crea il lettore appropriato (usando l'adapter per il vinile), riproduci la traccia tramite la funzione PlayMusic e stampa il risultato.

Verranno forniti i seguenti input:

  • Riga 1: tipo di lettore (digital o vinyl)
  • Riga 2: velocità RPM (solo se è vinile)
  • Ultima riga: nome della traccia da riprodurre

Ad esempio, dato:

digital
Bohemian Rhapsody

L'output dovrebbe essere:

Streaming: Bohemian Rhapsody

E dato:

vinyl
33
Abbey Road

L'output dovrebbe essere:

Playing Abbey Road (A side) at 33rpm

E dato:

vinyl
45
Blue Monday

L'output dovrebbe essere:

Playing Blue Monday (A side) at 45rpm

Nota come la funzione PlayMusic funzioni allo stesso modo con entrambi i lettori. Non sa che il lettore vinile viene adattato da un'interfaccia completamente diversa. L'adapter traduce dietro le quinte le chiamate all'interfaccia moderna nel formato legacy!

Provalo tu

package main

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

// PlayMusic usa l'interfaccia AudioPlayer per riprodurre musica
// Questa funzione funziona con qualsiasi implementazione di AudioPlayer
// TODO: Implementa questa funzione in modo che chiami player.Play(track) e restituisca il risultato
func PlayMusic(player AudioPlayer, track string) string {
	// TODO: Implementa questa funzione
	return ""
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// Leggi il tipo di lettore
	playerType, _ := reader.ReadString('\n')
	playerType = strings.TrimSpace(playerType)
	
	var player AudioPlayer
	var track string
	
	if playerType == "vinyl" {
		// Leggi la velocità in RPM per il vinile
		rpmStr, _ := reader.ReadString('\n')
		rpmStr = strings.TrimSpace(rpmStr)
		rpm, _ := strconv.Atoi(rpmStr)
		
		// Leggi il nome della traccia
		track, _ = reader.ReadString('\n')
		track = strings.TrimSpace(track)
		
		// TODO: Crea un VinylPlayer con il valore RPM indicato
		// TODO: Racchiudilo in un VinylAdapter
		// TODO: Assegnalo alla variabile player
		_ = rpm // Rimuovi questa riga quando usi rpm
	} else {
		// Leggi il nome della traccia
		track, _ = reader.ReadString('\n')
		track = strings.TrimSpace(track)
		
		// TODO: Crea un DigitalPlayer
		// TODO: Assegnalo alla variabile player
	}
	
	// TODO: Chiama PlayMusic e stampa il risultato
	_ = player // Rimuovi questa riga quando usi player
	_ = track  // Rimuovi questa riga quando usi track
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Go online