Menu
Coddy logo textTech

Modèle Adaptateur

Fait partie de la section Programmation Orientée Objet du Journey GO de Coddy. Leçon 92 sur 107.

Le patron Adaptateur permet à des interfaces incompatibles de fonctionner ensemble en enveloppant un type existant avec une nouvelle interface. Alors que Command encapsule des actions, Adaptateur traduit une interface en une autre que les clients attendent.

Imaginez que vous avez une ancienne imprimante qui utilise une signature de méthode différente de celle attendue par votre application :

// Interface cible utilisée par votre application
type Printer interface {
    Print(text string) string
}

// Imprimante héritée avec une interface incompatible
type OldPrinter struct{}

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

L’adaptateur encapsule le type hérité et implémente l’interface attendue :

type OldPrinterAdapter struct {
    oldPrinter OldPrinter
}

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

Désormais, l’ancienne imprimante fonctionne parfaitement avec le code qui attend l’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)"

Le modèle Adapter est précieux lors de l’intégration de bibliothèques tierces, de l’utilisation de code ancien ou lorsque vous devez utiliser des classes existantes qui ne correspondent pas aux exigences de votre interface. Il agit comme un pont sans modifier le code d’origine.

challenge icon

Défi

Facile

Construisons un système de lecteur multimédia à l’aide du modèle Adapter ! Vous disposez d’un lecteur audio moderne qui attend une interface unifiée, mais vous devez intégrer un équipement audio ancien qui utilise des signatures de méthodes complètement différentes. Votre adaptateur fera le lien, permettant à l’ancien matériel de fonctionner parfaitement avec le nouveau système.

Vous organiserez votre code sur trois fichiers :

  • player.go : définissez votre interface cible et un appareil audio ancien.

    Créez une interface AudioPlayer que votre système moderne attend, avec une méthode Play(track string) string qui prend le nom d’une piste et renvoie un message de lecture.

    Définissez également un appareil ancien qui ne correspond pas à cette interface :

    • la structure VinylPlayer avec un champ SpeedRPM (int). Elle possède une méthode DropNeedle(record string, side string) string qui renvoie Playing [record] ([side] side) at [speed]rpm

    L’interface de VinylPlayer est incompatible avec AudioPlayer. Elle nécessite deux paramètres et utilise un nom de méthode complètement différent.

  • adapter.go : créez votre adaptateur afin de rendre l’ancien appareil compatible.

    Construisez une structure VinylAdapter qui encapsule un VinylPlayer et implémente l’interface AudioPlayer. Lorsque Play est appelée, l’adaptateur doit appeler la méthode DropNeedle du lecteur de vinyles, en utilisant par défaut A pour le paramètre de face.

    Créez également un lecteur moderne à titre de comparaison :

    • structure DigitalPlayer : sa méthode Play renvoie Streaming: [track]
  • main.go : démontrez le fonctionnement des deux lecteurs via la même interface.

    Créez une fonction PlayMusic(player AudioPlayer, track string) string qui utilise l’interface pour lire de la musique. Cette fonction ne doit pas savoir ni se soucier de savoir si elle utilise un lecteur numérique ou un lecteur de vinyles adapté.

    Lisez un type de lecteur (digital ou vinyl) et, s’il s’agit de vinyles, lisez également la vitesse en RPM. Lisez ensuite le nom de la piste. Créez le lecteur approprié (en utilisant l’adaptateur pour les vinyles), lisez la piste via votre fonction PlayMusic et affichez le résultat.

Les entrées suivantes seront fournies :

  • Ligne 1 : type de lecteur (digital ou vinyl)
  • Ligne 2 : vitesse en RPM (uniquement pour les vinyles)
  • Dernière ligne : nom de la piste à lire

Par exemple, avec :

digital
Bohemian Rhapsody

Votre sortie doit être :

Streaming: Bohemian Rhapsody

Et avec :

vinyl
33
Abbey Road

Votre sortie doit être :

Playing Abbey Road (A side) at 33rpm

Et avec :

vinyl
45
Blue Monday

Votre sortie doit être :

Playing Blue Monday (A side) at 45rpm

Remarquez comment la fonction PlayMusic fonctionne de manière identique avec les deux lecteurs. Elle ne sait pas que le lecteur de vinyles est en réalité adapté à partir d’une interface complètement différente. L’adaptateur traduit en arrière-plan les appels à l’interface moderne au format ancien !

Essayez vous-même

package main

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

// PlayMusic utilise l'interface AudioPlayer pour jouer de la musique
// Cette fonction fonctionne avec n'importe quelle implémentation d'AudioPlayer
// TODO: Implémenter cette fonction pour appeler player.Play(track) et retourner le résultat
func PlayMusic(player AudioPlayer, track string) string {
	// TODO: Implémenter cette fonction
	return ""
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// Lire le type de lecteur
	playerType, _ := reader.ReadString('\n')
	playerType = strings.TrimSpace(playerType)
	
	var player AudioPlayer
	var track string
	
	if playerType == "vinyl" {
		// Lire la vitesse RPM pour le vinyle
		rpmStr, _ := reader.ReadString('\n')
		rpmStr = strings.TrimSpace(rpmStr)
		rpm, _ := strconv.Atoi(rpmStr)
		
		// Lire le nom de la piste
		track, _ = reader.ReadString('\n')
		track = strings.TrimSpace(track)
		
		// TODO: Créer un VinylPlayer avec le RPM donné
		// TODO: L'envelopper dans un VinylAdapter
		// TODO: Assigner à la variable player
		_ = rpm // Supprimer cette ligne lorsque vous utilisez rpm
	} else {
		// Lire le nom de la piste
		track, _ = reader.ReadString('\n')
		track = strings.TrimSpace(track)
		
		// TODO: Créer un DigitalPlayer
		// TODO: Assigner à la variable player
	}
	
	// TODO: Appeler PlayMusic et afficher le résultat
	_ = player // Supprimer cette ligne lorsque vous utilisez player
	_ = track  // Supprimer cette ligne lorsque vous utilisez track
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur Go en ligne