Start
Unternehmen
Buch-Katalog
Seminare
Leserservice
Comelio-Blog
Datenbanken
SQL
MS SQL Server
Oracle
PHP
UML
C#.NET

Operator-Überladung

Konvertierungen

Schnittstellen

Abstrakte Klassen

Delegation

Indexer

Code-Behind

Adapter-Muster

Dekorierer-Muster

Kompositum-Muster

XML Schema
XSLT

Übersicht

Comelio GmbH
Rellinghauser Straße 10
D-45128 Essen
Deutschland
Fon: 0201-437517-0
Fax: 0201-437517-10
info@comelio.com

Comelio GmbH
Goethestraße 34
D-13086 Berlin
Deutschland
info@comelio.com

Comelio GmbH (Ecos)
Glockengießerwall 17
D-20095 Hamburg
Deutschland
info@comelio.com

Comelio GmbH (Ecos)
Mainzer Landstraße 27-31
D-60329 Frankfurt
Deutschland
info@comelio.com

Comelio GmbH (Ecos)
Stiglmaierplatz/Dachauer Str. 37
D-80335 München
Deutschland
info@comelio.com

Comelio GmbH (Ecos)
Liebknechtstr. 33
D-70565 Stuttgart
Deutschland
info@comelio.com

Comelio GmbH
Nevinghoff 16
D-48147 Münster
Deutschland

Comelio GmbH
Friedrich - List - Platz 1
D-04103 Leipzig
Deutschland

Comelio GmbH
St. Johanner Strasse 41-43
D-66111 Saarbrücken
Deutschland

Comelio GmbH
Kaiser-Wilhem-Ring 27–29
D-50672 Köln
Deutschland

Comelio GmbH
Münsterstraße 248
D-40470 Düsseldorf
Deutschland

Comelio GmbH
Fürther Strasse
D-90429 Nürnberg
Deutschland

Comelio GmbH

Bremen
Deutschland

Comelio-Blog > C#.NET > Adapter-Muster

Entwurfsmuster (Design Patterns) in C#.NET: Adapter

Das Adapter-Muster stellt die Lösung für eine Problemsituation dar, in der man sehr gerne eine vorhandene Klasse nutzen möchte, ihre öffentlichen Komponenten allerdings nicht zu einer vorliegenden Schnittstelle passen. Dadurch lässt sich kein polymorphes Verhalten nutzen, sondern man müsste quasi eine neue Klasse erstellen, die die benötigte Schnittstelle implementiert und kann auf die vorliegende Klasse dann doch wiederum ohne Änderungen nicht zurückzugreifen. Dieser Artikel gibt eine beispielhafte Implementierung mit C#.NET an.

Kontakt

Anrede* Herr Frau
Vorname*
Nachname*
Firma
E-Mail*
Tel-Nr.
Bereich*
Freitext

Design Patterns: Adapter-Muster in C#.NET

Wie auch das Singleton-Muster, so ist auch das Adapter-Muster sowohl leicht erlernbar, einfach zu implementieren und oft einzusetzen. Typische Einsatzgebiete sind solche Projekte, in denen mit bereits fertigen Klassen gearbeitet werden soll, die allerdings nicht in die schöne, durch Schnittstellen oder abstrakte Klassen vorbereitet Ordnung passen wollen, sondern die für den Einsatz erst noch zurechtgestutzt werden sollen. Dabei ist es typischerweise nicht möglich, tatsächlich die Klassen zu ändern, weil sie entweder genau in der vorliegenden Weise bereits in diesem oder anderen Projekten bzw. Anwendungen genutzt werden, oder weil eine Änderung aufgrund fehlender Quelltextbearbeitungsmöglichkeit gar nicht durchgeführt werden kann.

Das Adapter-Muster stellt die Lösung für eine Problemsituation dar, in der man sehr gerne eine vorhandene Klasse nutzen möchte, ihre öffentlichen Komponenten allerdings nicht zu einer vorliegenden Schnittstelle passen. Dadurch lässt sich kein polymorphes Verhalten nutzen, sondern man müsste quasi eine neue Klasse erstellen, die die benötigte Schnittstelle implementiert und kann auf die vorliegende Klasse dann doch wiederum ohne Änderungen nicht zurückzugreifen.

Selbstverständlich wird die vorliegende Klasse aus unterschiedlichen Gründen gerade nicht geändert, sondern wird eine umhüllende Klasse erstellt, die exakt die geforderte Schnittstelle implementiert und daher das polymorphe Verhalten umsetzt. Innerhalb dieser umhüllenden Klasse, die als Adapter fungiert, erzeugt man nun das eigentlich benötigte Objekt der bereits vorhandenen Klasse und formt Methoden- oder Feld-/Eigenschaftsnamen, Parameterlisten und Rückgabewerte so passend um, bis man wie bei einem Adapter sowohl die Schnittstellenbedingungen erfüllt als auch der bereits vorliegenden Klasse Genüge getan hat.

public interface IKoerper {
   // Eigenschaften
   int laenge { get; }
   int breite { get; }
   int hoehe  { get; }
   // Methoden
   double errechneFlaeche();
}
Schnittstelle IKoerper

Ein Beispiel soll dieses recht einfache Vorgehen illustrieren. Aus nicht näher bekannten Gründen soll in die bereits bestehenden Formen eine weitere Form für die Abbildung eines Kreiszylinders eingefügt werden. Anstatt nun diese Klasse von Grund auf neu zu erstellen, stellt man fest, dass bereits eine von ihrer Implementierung, aber nicht von ihren öffentlichen Komponenten her nutzbare Klasse vorliegt. Diese heißt RundZylinder, speichert hoehe und breite als Felder und nicht als Eigenschaften und liefert die Fläche nicht als Methode unter dem Namen errechneFlaeche, sondern als Eigenschaft flaeche. Dennoch ist die komplizierte Formel zur Berechnung derselben genauso implementiert wie man sie für die Methode errechneFlaeche der IKoerper-Schnittstelle benutzen könnte. Diese Klasse soll benutzt werden, kann allerdings in der vorliegenden Form nicht zum Einsatz kommen, weil sie die IKoerper-Schnittstelle nicht im Geringsten implementiert.

public class RundZylinder {
    // Felder
    public int hoehe, radius;
    // Konstruktor
    public RundZylinder(int hoehe, int radius) {
        this.radius = radius;
        this.hoehe = hoehe;
    }
    // Eigenschaften
    public double flaeche {
        get {
            return 2 * Math.PI * radius * hoehe + 2 * Math.PI * Math.Pow(radius, radius);
        }
    }
}
Bereits fertige, aber für IKoerper unpassende Klasse

Statt nun eine neue KreisZylinder-Klasse zu erstellen, welche den Quelltext aus der anderen Klasse – sofern er überhaupt vorliegt – kopiert und von Grund auf neu implementiert, bedient man sich einer Adapter-Klasse, welche exakt die Schnittstelle IKoerper implementiert und genau ein Objekt vom Typ RundZyliner kapselt. Alle Anfragen bzgl. Eigenschaften und Methoden, welche die Schnittstelle voraussetzen und der Programmierung als Arbeitsauftrag liefern, werden nun genau auf dieses Objekt abgebildet. Dies ist im nachfolgenden Quelltext insbesondere sehr schön für die Methode errechneFlaeche zu sehen, die letztendlich einfach nur den Wert der Eigenschaft aus dem RundZylinder-Objekt, welches in dieser Klasse erstellt wird, zurückliefert.

public class KreisZylinder : IKoerper {
    // Felder
    private RundZylinder form;
    // Eigenschaften
    public int laenge {
        get { return 2 * form.radius; }
    }
    public int breite {
        get { return 2 * form.radius; }
    }
    public int hoehe {
        get { return form.hoehe; }
    }
    // Konstruktor
    public KreisZylinder (int hoehe, int radius) {
        form = new RundZylinder(hoehe, radius);
    }
    // Methoden
    public double errechneFlaeche(){
        return Math.Round(form.flaeche,2);
    }
}
Umhüllende Adapter-Klasse für fertige Lösung

Die ganze Arbeit macht natürlich nur Sinn, wenn ich das dadurch nutzbare polymorphe Verhalten, welches durch die Schnittstelle aufgebaut wird, auch tatsächlich nutze. In der FormFabrik-Klasse, die hier als Klientenklasse auftritt und zufällig unterschiedliche geometrische Objekte erzeugt, lässt sich nun ganz einfach auch ein Kreiszylinder mit der bereits fertigen Implementierung aus der RundZylinder-Klasse aufrufen. Da man ausschließlich mit dem auf Basis von IKoerper erstellten Adapter arbeitet und nicht mit der originalen Klasse, kann man diesen Adapter zurückliefern, der das eigentlich unpassende RundZylinder-Objekt umhüllt und die öffentlichen Komponenten auf dieses gekapselte Objekt anwendet.

public class FormFabrik  {
  public IKoerper erzeugeForm() {
     // .. Zufallszahlenerzeugung
     else if (zahl >= 2 & zahl <5){
        return new KreisZylinder(3, 2);
     }
    // else...
  }
}
Klientenklasse, die nur IKoerper verarbeiten kann

Zum Schluss folgt noch das UML-Diagramm, das für dieses Beispiel entsteht und für das Muster sehr charakteristisch ist. Innerhalb des Adapters liegt eine Komposition vor, da es die Entstehung und Zerstörung eines anderen Objektes, welches es für die Schnittstelle adaptiert / anpasst, kontrolliert. Zusätzlich wird das adaptierte Objekt automatisch zerstört, wenn das Adapter-Objekt zerstört wird. Der Adapter fügt sich passend in die Gruppe vorhandener Klassen ein, die alle jeweils eine bestimmte Schnittstelle implementieren. Daraus folgt, dass also auch eine Klientenklasse, die sich hier auf die Schnittstelle bezieht, ebenfalls mit dem adaptierten Objekt unter Verwendung eines Adapters arbeiten kann.

Adapter-Muster

Adapter-Muster

    Comelio GmbH C#.NET - Adapter-Muster - Design Patterns / Entwurfsmuster Entwurfsmuster Programmierung Tutorial Microsoft C#.NET Beispiel Anleitung .NET Syntax Code Erlangen Wolfsburg Leipzig Bochum Rügen Ingolstadt Bonn Göttingen Andernach Koblenz Bremen Koblenz Heidelberg Ludwigshafen Würzuburg Köln Hannover Frankfurt Hamburg Stuttgart Magdeburg Lübeck Berlin Zwickau Kassel München Kiel Freiburg Mannheim Ol AachenComelio GmbH C#.NET - Adapter-Muster - Design Patterns / Entwurfsmuster Entwurfsmuster Programmierung Tutorial Microsoft C#.NET Beispiel Anleitung .NET Syntax Code Erlangen Wolfsburg Leipzig Bochum Rügen Ingolstadt Bonn Göttingen Andernach Koblenz Bremen Koblenz Heidelberg Ludwigshafen Würzuburg Köln Hannover Frankfurt Hamburg Stuttgart Magdeburg Lübeck Berlin Zwickau Kassel München Kiel Freiburg Mannheim Ol AachenComelio GmbH C#.NET - Adapter-Muster - Design Patterns / Entwurfsmuster Entwurfsmuster Programmierung Tutorial Microsoft C#.NET Beispiel Anleitung .NET Syntax Code Erlangen Wolfsburg Leipzig Bochum Rügen Ingolstadt Bonn Göttingen Andernach Koblenz Bremen Koblenz Heidelberg Ludwigshafen Würzuburg Köln Hannover Frankfurt Hamburg Stuttgart Magdeburg Lübeck Berlin Zwickau Kassel München Kiel Freiburg Mannheim Ol AachenComelio GmbH C#.NET - Adapter-Muster - Design Patterns / Entwurfsmuster Entwurfsmuster Programmierung Tutorial Microsoft C#.NET Beispiel Anleitung .NET Syntax Code Erlangen Wolfsburg Leipzig Bochum Rügen Ingolstadt Bonn Göttingen Andernach Koblenz Bremen Koblenz Heidelberg Ludwigshafen Würzuburg Köln Hannover Frankfurt Hamburg Stuttgart Magdeburg Lübeck Berlin Zwickau Kassel München Kiel Freiburg Mannheim Ol AachenComelio GmbH C#.NET - Adapter-Muster - Design Patterns / Entwurfsmuster Entwurfsmuster Programmierung Tutorial Microsoft C#.NET Beispiel Anleitung .NET Syntax Code Erlangen Wolfsburg Leipzig Bochum Rügen Ingolstadt Bonn Göttingen Andernach Koblenz Bremen Koblenz Heidelberg Ludwigshafen Würzuburg Köln Hannover Frankfurt Hamburg Stuttgart Magdeburg Lübeck Berlin Zwickau Kassel München Kiel Freiburg Mannheim Ol AachenComelio GmbH C#.NET - Adapter-Muster - Design Patterns / Entwurfsmuster Entwurfsmuster Programmierung Tutorial Microsoft C#.NET Beispiel Anleitung .NET Syntax Code Erlangen Wolfsburg Leipzig Bochum Rügen Ingolstadt Bonn Göttingen Andernach Koblenz Bremen Koblenz Heidelberg Ludwigshafen Würzuburg Köln Hannover Frankfurt Hamburg Stuttgart Magdeburg Lübeck Berlin Zwickau Kassel München Kiel Freiburg Mannheim Ol AachenComelio GmbH C#.NET - Adapter-Muster - Design Patterns / Entwurfsmuster Entwurfsmuster Programmierung Tutorial Microsoft C#.NET Beispiel Anleitung .NET Syntax Code Erlangen Wolfsburg Leipzig Bochum Rügen Ingolstadt Bonn Göttingen Andernach Koblenz Bremen Koblenz Heidelberg Ludwigshafen Würzuburg Köln Hannover Frankfurt Hamburg Stuttgart Magdeburg Lübeck Berlin Zwickau Kassel München Kiel Freiburg Mannheim Ol AachenComelio GmbH C#.NET - Adapter-Muster - Design Patterns / Entwurfsmuster Entwurfsmuster Programmierung Tutorial Microsoft C#.NET Beispiel Anleitung .NET Syntax Code Erlangen Wolfsburg Leipzig Bochum Rügen Ingolstadt Bonn Göttingen Andernach Koblenz Bremen Koblenz Heidelberg Ludwigshafen Würzuburg Köln Hannover Frankfurt Hamburg Stuttgart Magdeburg Lübeck Berlin Zwickau Kassel München Kiel Freiburg Mannheim Ol AachenComelio GmbH C#.NET - Adapter-Muster - Design Patterns / Entwurfsmuster Entwurfsmuster Programmierung Tutorial Microsoft C#.NET Beispiel Anleitung .NET Syntax Code Erlangen Wolfsburg Leipzig Bochum Rügen Ingolstadt Bonn Göttingen Andernach Koblenz Bremen Koblenz Heidelberg Ludwigshafen Würzuburg Köln Hannover Frankfurt Hamburg Stuttgart Magdeburg Lübeck Berlin Zwickau Kassel München Kiel Freiburg Mannheim Ol Aachen
Seminare