Menu
Coddy logo textTech

Patron Adaptateur

Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy — leçon 57 sur 70.

Le pattern Adapter est un patron de structure qui permet à des interfaces incompatibles de travailler ensemble. Il agit comme un pont entre deux classes, convertissant l'interface d'une classe en une interface attendue par les clients. Pensez-y comme à un adaptateur secteur qui vous permet de brancher un appareil européen sur une prise américaine.

Ce patron est particulièrement utile lorsque vous souhaitez utiliser une classe existante mais que son interface ne correspond pas à ce dont votre code a besoin. Au lieu de modifier la classe d'origine (que vous ne contrôlez peut-être pas), vous créez un adaptateur qui l'enveloppe :

// Classe existante avec une interface incompatible
public class OldPrinter
{
    public void PrintMessage(string msg) => Console.WriteLine($"Old: {msg}");
}

// Interface attendue par votre code
public interface IPrinter
{
    void Print(string text);
}

// L'adaptateur comble l'écart
public class PrinterAdapter : IPrinter
{
    private OldPrinter _oldPrinter;
    
    public PrinterAdapter(OldPrinter oldPrinter)
    {
        _oldPrinter = oldPrinter;
    }
    
    public void Print(string text)
    {
        _oldPrinter.PrintMessage(text);  // Délègue à l'ancienne interface
    }
}

Désormais, votre code peut fonctionner avec l'ancienne imprimante via l'interface attendue :

OldPrinter legacy = new OldPrinter();
IPrinter printer = new PrinterAdapter(legacy);

printer.Print("Hello");  // Ancien : Hello

Le pattern Adapter est inestimable lors de l'intégration de bibliothèques tierces ou de code hérité dans votre application. Le code client travaille avec l'interface IPrinter, ignorant complètement qu'une ancienne classe incompatible effectue le travail réel en coulisses.

challenge icon

Défi

Facile

Construisons un système de lecteur multimédia en utilisant le motif Adaptateur (Adapter pattern). Vous disposez d'une bibliothèque audio existante qui lit des fichiers MP3, mais votre application a besoin d'une interface unifiée capable de gérer différents types de médias. Vous allez créer un adaptateur pour combler cet écart, permettant à votre lecteur multimédia moderne de fonctionner de manière transparente avec la bibliothèque audio héritée.

Vous organiserez votre code sur trois fichiers :

  • LegacyAudio.cs : Cela représente une bibliothèque existante que vous ne pouvez pas modifier. Créez une classe LegacyAudioPlayer dans l'espace de noms MediaSystem avec une méthode PlayMp3(string filename) qui retourne la chaîne "Playing MP3: {filename}". C'est votre "adaptee" - la classe avec l'interface incompatible.
  • MediaAdapter.cs : Créez l'interface et l'adaptateur dans le même espace de noms. Définissez une interface IMediaPlayer avec une méthode Play(string filename) qui retourne une chaîne de caractères. Ensuite, créez une classe MediaPlayerAdapter qui implémente IMediaPlayer. Votre adaptateur doit envelopper une instance de LegacyAudioPlayer (passée via le constructeur) et traduire l'appel Play vers la méthode PlayMp3 du lecteur hérité.
  • Program.cs : Rassemblez le tout en créant le lecteur hérité, en l'enveloppant dans votre adaptateur et en utilisant l'adaptateur via l'interface IMediaPlayer. Cela démontre comment le code client peut travailler avec l'interface moderne tandis que l'adaptateur gère la communication avec le système hérité en coulisses.

Vous recevrez une entrée :

  • Le nom du fichier à lire (par exemple, song.mp3)

Créez un LegacyAudioPlayer, enveloppez-le dans un MediaPlayerAdapter, puis appelez Play sur l'adaptateur en utilisant l'interface IMediaPlayer et affichez le résultat.

Par exemple, si l'entrée est favorite_track.mp3, la sortie doit être :

Playing MP3: favorite_track.mp3

La beauté de ce motif est que votre code principal interagit uniquement avec IMediaPlayer - il n'a aucune idée qu'une bibliothèque audio héritée effectue le travail réel. Si vous devez plus tard prendre en charge une autre bibliothèque héritée, il vous suffira de créer un nouvel adaptateur sans modifier le code client !

Aide-mémoire

Le pattern Adaptateur (Adapter pattern) est un pattern structurel qui permet à des interfaces incompatibles de fonctionner ensemble en agissant comme un pont entre deux classes.

Ce pattern convertit l'interface d'une classe en une interface attendue par les clients, ce qui est utile lorsque vous souhaitez utiliser une classe existante mais que son interface ne correspond pas aux besoins de votre code.

Structure de base :

// Existing class with incompatible interface (Adaptee)
public class OldPrinter
{
    public void PrintMessage(string msg) => Console.WriteLine($"Old: {msg}");
}

// Target interface your code expects
public interface IPrinter
{
    void Print(string text);
}

// Adapter bridges the gap
public class PrinterAdapter : IPrinter
{
    private OldPrinter _oldPrinter;
    
    public PrinterAdapter(OldPrinter oldPrinter)
    {
        _oldPrinter = oldPrinter;
    }
    
    public void Print(string text)
    {
        _oldPrinter.PrintMessage(text);  // Delegates to old interface
    }
}

Utilisation :

OldPrinter legacy = new OldPrinter();
IPrinter printer = new PrinterAdapter(legacy);

printer.Print("Hello");  // Old: Hello

Le code client travaille avec l'interface cible, sans savoir qu'une classe incompatible effectue le travail réel en coulisses. Ce pattern est particulièrement précieux lors de l'intégration de bibliothèques tierces ou de code hérité (legacy).

Essayez vous-même

using System;
using MediaSystem;

class Program
{
    public static void Main(string[] args)
    {
        // Lire l'entrée du nom de fichier
        string filename = Console.ReadLine();
        
        // TODO: Créer une instance de LegacyAudioPlayer
        
        // TODO: L'envelopper dans un MediaPlayerAdapter
        
        // TODO: Utiliser l'adaptateur via l'interface IMediaPlayer
        // et afficher le résultat de l'appel à Play avec le nom de fichier
    }
}
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