Menu
Coddy logo textTech

Adapter-Muster

Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 95 von 110.

Das Adapter-Muster ermöglicht es inkompatiblen Schnittstellen, zusammenzuarbeiten. Es fungiert als Brücke zwischen zwei Klassen, die andernfalls nicht zusammenarbeiten könnten, indem es eine bestehende Klasse mit einer neuen Schnittstelle umhüllt, die Clients erwarten. Dies ist besonders nützlich, wenn Drittanbieter-Bibliotheken oder Legacy-Code in Ihre Anwendung integriert werden.

Stellen Sie sich vor, Sie haben ein System, das mit JSON-Daten arbeitet, aber Sie müssen eine Komponente integrieren, die nur XML ausgibt. Anstatt eine der beiden Klassen zu ändern, erstellen Sie einen Adapter, der zwischen ihnen übersetzt:

// Vorhandene Schnittstelle, die Ihr System erwartet
abstract class JsonData {
  String getJson();
}

// Legacy-Klasse mit inkompatibler Schnittstelle
class XmlService {
  String getXml() {
    return '<data><name>John</name></data>';
  }
}

// Der Adapter macht XmlService mit JsonData kompatibel
class XmlToJsonAdapter implements JsonData {
  final XmlService _xmlService;

  XmlToJsonAdapter(this._xmlService);

  @override
  String getJson() {
    String xml = _xmlService.getXml();
    // XML in JSON umwandeln (vereinfacht)
    return '{"name": "John"}';
  }
}

void main() {
  var xmlService = XmlService();
  var adapter = XmlToJsonAdapter(xmlService);

  print(adapter.getJson());  // {"name": "John"}
}

Der XmlToJsonAdapter umschließt den XmlService und implementiert das JsonData-Interface. Der Client-Code arbeitet mit dem vertrauten JsonData-Interface, ohne zu wissen, dass die Daten ursprünglich aus einer XML-Quelle stammten. Der Adapter übernimmt die gesamte Übersetzung intern.

Verwenden Sie das Adapter-Muster, wenn Sie eine bestehende Klasse verwenden möchten, deren Schnittstelle jedoch nicht Ihren Anforderungen entspricht, oder wenn Sie eine wiederverwendbare Klasse erstellen müssen, die mit Klassen mit inkompatiblen Schnittstellen zusammenarbeitet.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Media-Player-Adaptersystem bauen! Stellen Sie sich vor, Sie haben ein modernes Audiosystem, das erwartet, dass alle Medienquellen Audio über eine Standardschnittstelle bereitstellen, aber Sie müssen einen alten Plattenspieler integrieren, der eine völlig andere Art der Tonerzeugung hat.

Sie werden zwei Dateien erstellen, um Ihre Implementierung des Adapter-Musters zu organisieren:

  • media_adapter.dart: Diese Datei enthält Ihre Interface- und Adapter-Klassen. Definieren Sie eine abstrakte Klasse AudioSource, die Ihr modernes System erwartet – sie sollte eine Methode String playAudio() haben, die die Audioausgabe als String zurückgibt. Erstellen Sie dann eine Klasse VinylPlayer, die das Altgerät repräsentiert – sie hat ein Feld trackName und eine Methode String spinRecord(), die *crackle* Playing vinyl: [trackName] *crackle* zurückgibt. Erstellen Sie schließlich einen VinylAdapter, der AudioSource implementiert und einen VinylPlayer kapselt. Die Methode playAudio() des Adapters sollte die Methode spinRecord() des Plattenspielers aufrufen und das Ergebnis zurückgeben – so werden die inkompatiblen Schnittstellen überbrückt.
  • main.dart: Importieren Sie Ihre Media-Adapter-Datei und demonstrieren Sie, wie der Adapter den alten Plattenspieler mit Code kompatibel macht, der das moderne AudioSource-Interface erwartet. Erstellen Sie einen VinylPlayer mit dem Tracknamen Bohemian Rhapsody. Erstellen Sie dann einen VinylAdapter, der diesen Plattenspieler kapselt. Speichern Sie den Adapter in einer Variablen vom Typ AudioSource, um zu beweisen, dass er der erwarteten Schnittstelle entspricht. Rufen Sie playAudio() auf Ihrer Audioquelle auf und geben Sie das Ergebnis aus.

Das Schöne an diesem Muster ist, dass Ihr Hauptcode mit der Standard-Schnittstelle AudioSource arbeitet – er muss nicht wissen, dass hinter den Kulissen ein alter Plattenspieler die eigentliche Arbeit erledigt!

Erwartete Ausgabe:

*crackle* Playing vinyl: Bohemian Rhapsody *crackle*

Spickzettel

Das Adapter-Muster ermöglicht es inkompatiblen Schnittstellen, zusammenzuarbeiten, indem es als Brücke zwischen zwei Klassen fungiert, die andernfalls nicht kooperieren könnten.

Der Adapter umschließt eine bestehende Klasse mit einer neuen Schnittstelle, die Clients erwarten, was ihn nützlich macht, wenn Drittanbieter-Bibliotheken oder Legacy-Code integriert werden.

Grundstruktur

// Ziel-Schnittstelle, die Clients erwarten
abstract class JsonData {
  String getJson();
}

// Bestehende Klasse mit inkompatibler Schnittstelle
class XmlService {
  String getXml() {
    return '<data><name>John</name></data>';
  }
}

// Adapter macht XmlService kompatibel mit JsonData
class XmlToJsonAdapter implements JsonData {
  final XmlService _xmlService;

  XmlToJsonAdapter(this._xmlService);

  @override
  String getJson() {
    String xml = _xmlService.getXml();
    // XML in JSON umwandeln
    return '{"name": "John"}';
  }
}

Verwendung

void main() {
  var xmlService = XmlService();
  var adapter = XmlToJsonAdapter(xmlService);

  print(adapter.getJson());  // {"name": "John"}
}

Der Adapter implementiert die Ziel-Schnittstelle, während er die inkompatible Klasse umschließt. Der Client-Code arbeitet mit der vertrauten Schnittstelle, ohne die zugrunde liegende Implementierung zu kennen.

Wann man es verwendet: Wenn Sie eine bestehende Klasse verwenden müssen, deren Schnittstelle jedoch nicht Ihren Anforderungen entspricht, oder wenn Sie eine wiederverwendbare Klasse erstellen, die mit Klassen mit inkompatiblen Schnittstellen zusammenarbeitet.

Probier es selbst

import 'media_adapter.dart';

void main() {
  // TODO: Erstelle einen VinylPlayer mit dem Track-Namen "Bohemian Rhapsody"
  
  // TODO: Erstelle einen VinylAdapter, der den Vinyl-Player umschließt
  
  // TODO: Speichere den Adapter in einer Variable vom Typ AudioSource
  
  // TODO: Rufe playAudio() auf deiner Audioquelle auf und gib das Ergebnis 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