Menu
Coddy logo textTech

Padrão Adapter

Parte da seção Programação Orientada a Objetos do Journey de GO da Coddy. Lição 92 de 107.

O padrão Adapter permite que interfaces incompatíveis trabalhem juntas ao envolver um tipo existente com uma nova interface. Enquanto Command encapsula ações, Adapter traduz uma interface em outra que os clientes esperam.

Imagine que você tenha uma impressora legada que usa uma assinatura de método diferente da esperada pela sua aplicação:

// Interface alvo que sua aplicação usa
type Printer interface {
    Print(text string) string
}

// Impressora legada com interface incompatível
type OldPrinter struct{}

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

O adaptador envolve o tipo legado e implementa a interface esperada:

type OldPrinterAdapter struct {
    oldPrinter OldPrinter
}

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

Agora, a impressora legada funciona perfeitamente com o código que espera a interface Printer:

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

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

O padrão Adapter é inestimável ao integrar bibliotecas de terceiros, trabalhar com código legado ou quando você precisa usar classes existentes que não correspondem aos requisitos da sua interface. Ele atua como uma ponte sem modificar o código original.

challenge icon

Desafio

Fácil

Vamos criar um sistema de reprodução de mídia usando o padrão Adapter! Você tem um reprodutor de áudio moderno que espera uma interface unificada, mas precisa integrar equipamentos de áudio legados que usam assinaturas de métodos completamente diferentes. Seu adaptador fará a ponte entre essa lacuna, permitindo que o hardware antigo funcione perfeitamente com o novo sistema.

Você organizará seu código em três arquivos:

  • player.go: defina sua interface-alvo e um dispositivo de áudio legado.

    Crie uma interface AudioPlayer que seu sistema moderno espera, com um método Play(track string) string que recebe o nome de uma faixa e retorna uma mensagem de reprodução.

    Defina também um dispositivo legado que não corresponde a essa interface:

    • struct VinylPlayer com um campo SpeedRPM (int). Ele possui um método DropNeedle(record string, side string) string que retorna Playing [record] ([side] side) at [speed]rpm

    A interface de VinylPlayer é incompatível com AudioPlayer. Ela exige dois parâmetros e usa um nome de método completamente diferente.

  • adapter.go: crie seu adaptador para tornar o dispositivo legado compatível.

    Crie um struct VinylAdapter que encapsule um VinylPlayer e implemente a interface AudioPlayer. Quando Play for chamado, o adaptador deverá chamar o método DropNeedle do reprodutor de vinil, usando A como padrão para o parâmetro do lado.

    Crie também um reprodutor moderno para comparação:

    • struct DigitalPlayer: seu método Play retorna Streaming: [track]
  • main.go: demonstre os dois reprodutores funcionando por meio da mesma interface.

    Crie uma função PlayMusic(player AudioPlayer, track string) string que use a interface para reproduzir música. Essa função não deve saber nem se importar se está usando um reprodutor digital ou um reprodutor de vinil adaptado.

    Leia um tipo de reprodutor (digital ou vinyl) e, se for vinyl, leia também a velocidade em RPM. Em seguida, leia o nome da faixa. Crie o reprodutor apropriado (usando o adaptador para vinyl), reproduza a faixa por meio da função PlayMusic e imprima o resultado.

As entradas a seguir serão fornecidas:

  • Linha 1: tipo de reprodutor (digital ou vinyl)
  • Linha 2: velocidade em RPM (somente se for vinyl)
  • Última linha: nome da faixa a ser reproduzida

Por exemplo, dada a entrada:

digital
Bohemian Rhapsody

Sua saída deverá ser:

Streaming: Bohemian Rhapsody

E dada a entrada:

vinyl
33
Abbey Road

Sua saída deverá ser:

Playing Abbey Road (A side) at 33rpm

E dada a entrada:

vinyl
45
Blue Monday

Sua saída deverá ser:

Playing Blue Monday (A side) at 45rpm

Observe como a função PlayMusic funciona de forma idêntica com os dois reprodutores. Ela não faz ideia de que o reprodutor de vinil está, na verdade, sendo adaptado de uma interface completamente diferente. O adaptador traduz as chamadas da interface moderna para o formato legado nos bastidores!

Experimente você mesmo

package main

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

// PlayMusic usa a interface AudioPlayer para tocar música
// Esta função funciona com qualquer implementação de AudioPlayer
// TODO: Implemente esta função para chamar player.Play(track) e retornar o resultado
func PlayMusic(player AudioPlayer, track string) string {
	// TODO: Implemente esta função
	return ""
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// Lê o tipo de player
	playerType, _ := reader.ReadString('\n')
	playerType = strings.TrimSpace(playerType)
	
	var player AudioPlayer
	var track string
	
	if playerType == "vinyl" {
		// Lê a velocidade RPM para vinyl
		rpmStr, _ := reader.ReadString('\n')
		rpmStr = strings.TrimSpace(rpmStr)
		rpm, _ := strconv.Atoi(rpmStr)
		
		// Lê o nome da track
		track, _ = reader.ReadString('\n')
		track = strings.TrimSpace(track)
		
		// TODO: Crie um VinylPlayer com o RPM fornecido
		// TODO: Envolva-o em um VinylAdapter
		// TODO: Atribua à variável player
		_ = rpm // Remova esta linha quando usar rpm
	} else {
		// Lê o nome da track
		track, _ = reader.ReadString('\n')
		track = strings.TrimSpace(track)
		
		// TODO: Crie um DigitalPlayer
		// TODO: Atribua à variável player
	}
	
	// TODO: Chame PlayMusic e imprima o resultado
	_ = player // Remova esta linha quando você usar player
	_ = track  // Remova esta linha quando você usar track
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de Go online