Menu
Coddy logo textTech

Adapter-Muster

Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy — Lektion 57 von 70.

Das Adapter-Muster ist ein Strukturmuster, das es inkompatiblen Schnittstellen ermöglicht, zusammenzuarbeiten. Es fungiert als Brücke zwischen zwei Klassen und wandelt die Schnittstelle einer Klasse in eine Schnittstelle um, die Clients erwarten. Stellen Sie es sich wie einen Reiseadapter vor, mit dem Sie ein europäisches Gerät an eine amerikanische Steckdose anschließen können.

Dieses Muster ist besonders nützlich, wenn Sie eine bestehende Klasse verwenden möchten, deren Schnittstelle jedoch nicht den Anforderungen Ihres Codes entspricht. Anstatt die ursprüngliche Klasse zu ändern (die Sie möglicherweise nicht kontrollieren können), erstellen Sie einen Adapter, der sie umschließt:

// Bestehende Klasse mit inkompatibler Schnittstelle
public class OldPrinter
{
    public void PrintMessage(string msg) => Console.WriteLine($"Old: {msg}");
}

// Schnittstelle, die Ihr Code erwartet
public interface IPrinter
{
    void Print(string text);
}

// Adapter überbrückt die Lücke
public class PrinterAdapter : IPrinter
{
    private OldPrinter _oldPrinter;
    
    public PrinterAdapter(OldPrinter oldPrinter)
    {
        _oldPrinter = oldPrinter;
    }
    
    public void Print(string text)
    {
        _oldPrinter.PrintMessage(text);  // Delegiert an die alte Schnittstelle
    }
}

Jetzt kann Ihr Code über die erwartete Schnittstelle mit dem alten Drucker arbeiten:

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

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

Das Adapter-Muster ist von unschätzbarem Wert, wenn Sie Bibliotheken von Drittanbietern oder Legacy-Code in Ihre Anwendung integrieren. Der Client-Code arbeitet mit der IPrinter-Schnittstelle und ist sich völlig unbewusst darüber, dass eine alte, inkompatible Klasse im Hintergrund die eigentliche Arbeit verrichtet.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Mediaplayer-System unter Verwendung des Adapter-Musters erstellen. Sie verfügen über eine bestehende Audio-Bibliothek, die MP3-Dateien abspielt, aber Ihre Anwendung benötigt eine einheitliche Schnittstelle, die verschiedene Medientypen verarbeiten kann. Sie werden einen Adapter erstellen, um diese Lücke zu schließen, sodass Ihr moderner Mediaplayer nahtlos mit der veralteten Audio-Bibliothek zusammenarbeiten kann.

Sie werden Ihren Code über drei Dateien organisieren:

  • LegacyAudio.cs: Dies repräsentiert eine bestehende Bibliothek, die Sie nicht ändern können. Erstellen Sie eine Klasse LegacyAudioPlayer im Namespace MediaSystem mit einer Methode PlayMp3(string filename), die den String "Playing MP3: {filename}" zurückgibt. Dies ist Ihr "Adaptee" – die Klasse mit der inkompatiblen Schnittstelle.
  • MediaAdapter.cs: Erstellen Sie das Interface und den Adapter im selben Namespace. Definieren Sie ein IMediaPlayer-Interface mit einer Methode Play(string filename), die einen String zurückgibt. Erstellen Sie dann eine Klasse MediaPlayerAdapter, die IMediaPlayer implementiert. Ihr Adapter sollte eine LegacyAudioPlayer-Instanz kapseln (die über den Konstruktor übergeben wird) und den Play-Aufruf in die PlayMp3-Methode des Legacy-Players übersetzen.
  • Program.cs: Führen Sie alles zusammen, indem Sie den Legacy-Player erstellen, ihn in Ihren Adapter einhüllen und den Adapter über das IMediaPlayer-Interface verwenden. Dies demonstriert, wie Client-Code mit der modernen Schnittstelle arbeiten kann, während der Adapter im Hintergrund die Kommunikation mit dem Legacy-System übernimmt.

Sie erhalten eine Eingabe:

  • Den Dateinamen, der abgespielt werden soll (z. B. song.mp3)

Erstellen Sie einen LegacyAudioPlayer, hüllen Sie ihn in einen MediaPlayerAdapter ein, rufen Sie dann Play auf dem Adapter über das IMediaPlayer-Interface auf und geben Sie das Ergebnis aus.

Wenn die Eingabe beispielsweise favorite_track.mp3 ist, sollte die Ausgabe wie folgt lauten:

Playing MP3: favorite_track.mp3

Das Schöne an diesem Muster ist, dass Ihr Hauptcode nur mit IMediaPlayer interagiert – er hat keine Ahnung, dass eine veraltete Audio-Bibliothek die eigentliche Arbeit erledigt. Wenn Sie später eine andere Legacy-Bibliothek unterstützen müssen, erstellen Sie einfach einen neuen Adapter, ohne den Client-Code zu ändern!

Spickzettel

Das Adapter-Muster ist ein Strukturmuster, das es inkompatiblen Schnittstellen ermöglicht, zusammenzuarbeiten, indem es als Brücke zwischen zwei Klassen fungiert.

Das Muster wandelt die Schnittstelle einer Klasse in eine Schnittstelle um, die Clients erwarten. Dies ist nützlich, wenn Sie eine bestehende Klasse verwenden möchten, deren Schnittstelle jedoch nicht den Anforderungen Ihres Codes entspricht.

Grundstruktur:

// Bestehende Klasse mit inkompatibler Schnittstelle (Adaptee)
public class OldPrinter
{
    public void PrintMessage(string msg) => Console.WriteLine($"Old: {msg}");
}

// Ziel-Schnittstelle, die Ihr Code erwartet
public interface IPrinter
{
    void Print(string text);
}

// Adapter überbrückt die Lücke
public class PrinterAdapter : IPrinter
{
    private OldPrinter _oldPrinter;
    
    public PrinterAdapter(OldPrinter oldPrinter)
    {
        _oldPrinter = oldPrinter;
    }
    
    public void Print(string text)
    {
        _oldPrinter.PrintMessage(text);  // Delegiert an die alte Schnittstelle
    }
}

Verwendung:

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

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

Der Client-Code arbeitet mit der Ziel-Schnittstelle, ohne zu wissen, dass eine inkompatible Klasse im Hintergrund die eigentliche Arbeit verrichtet. Dieses Muster ist besonders wertvoll bei der Integration von Drittanbieter-Bibliotheken oder Legacy-Code.

Probier es selbst

using System;
using MediaSystem;

class Program
{
    public static void Main(string[] args)
    {
        // Lies die Dateinamen-Eingabe ein
        string filename = Console.ReadLine();
        
        // TODO: Erstelle eine LegacyAudioPlayer-Instanz
        
        // TODO: Umschließe sie mit einem MediaPlayerAdapter
        
        // TODO: Verwende den Adapter über das IMediaPlayer-Interface
        // und gib das Ergebnis des Aufrufs von Play mit dem Dateinamen aus
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung