Wenn professionelle Softwareentwickler/innen und IT-Architekt/innen mit Entwurfsmustern arbeiten, werden sie sich früher oder später mit den Mustern Adapter, Dekorierer, Fassade und Wrapper auseinandersetzen müssen. Alle vier Muster beschreiben Situationen, in denen ein neues Bindeglied mit speziellen Aufgaben zwischen zwei Klassen oder Komponenten geschaltet wird. Durch diese Gemeinsamkeit ähneln sich die Muster auf den ersten Blick stark, weshalb bei deren Einsatz in der Praxis immer wieder unnötige Missverständnisse auftreten. Solche Missverständnisse wirken sich sogar bis in die Literatur aus, wo diverse Autor/innen die Behauptung aufstellen, manche dieser Muster seien identisch oder verhielten sich zumindest in einer „ist-ein“-Beziehung zueinander. Das resultierende Gewirr möchte ich in diesem Artikel auflösen und klar benennen, was die jeweiligen Unterschiede und Einsatzszenarien sind. Aus Gründen der Verständlichkeit werde ich dabei nicht auf Implementierungsdetails eingehen, sondern lediglich aufzeigen, unter welchen Bedingungen welche Muster vorranging Anwendung finden – wohl wissend, dass sie natürlich auch geschickt kombiniert werden können.
Wir helfen Ihnen dabei, die Herausforderungen der IT-Architektur zu meistern! Entdecken Sie unsere CampusLab-Kurse zu diesem Thema:
- Objektorientierte Programmierung mit Java
- Gestaltung von IT-Architekturen
Beginnen wir zunächst mit dem Adapter-Muster. Es ist Teil des gemeinhin bekannten Entwurfsmusterkatalogs der „Gang of Four“ und wird dort als „Strukturmuster“ geführt (Gamma 2009). Ein Adapter wird eingesetzt, wenn es eine inkompatible Schnittstelle zwischen zwei bereits bestehenden (!) Komponenten gibt (s. Abbildung). Dass beide Komponenten bereits fertig entwickelt sein müssen, ist eine entscheidende Vorbedingung für den Einsatz des Musters. Schließlich kann eine rechtzeitig erkannte Inkompatibilität während der Entwicklung durch Anpassung der Schnittstelle schnell beseitigt werden – ganz ohne Adapter.
Der Dekorierer gehört ebenfalls zu den Strukturmustern der Gang of Four. Er wird hier deshalb von den anderen Mustern abgegrenzt, weil er eine Zeit lang im genannten Katalog unter „Wrapper“ firmierte. Ein Dekorierer wird dann eingesetzt, wenn eine bestehende Klasse um zusätzliche Funktionalität erweitert werden soll. Unerfahrene Entwickler/innen werden hier intuitiv nach dem Werkzeug der Vererbung greifen und die zusätzliche Funktionalität mithilfe von Unterklassen hinzufügen. Das mag zwar übersichtlicher erscheinen, bietet aber weniger Flexibilität. Im Unterschied zum Adapter verändert der Dekorierer nur die Funktionalität der nachgeschalteten Klasse, nicht deren Schnittstelle (s. Abbildung).
Fahren wir mit der Fassade fort. Sie ist das dritte hier vorgestellte Strukturmuster der Gang of Four. Eine Fassade wird oftmals mit den anderen Mustern verwechselt, weil es sich ebenfalls um einen Baustein handelt, der als Bindeglied zwischen Klassen bzw. Komponenten geschaltet wird. Sie wird dann korrekt eingesetzt, wenn eine Komponente nach außen nur über genau eine Schnittstelle verwendet werden soll. Gemäß dem Prinzip der Kapselung werden die von den Klassen der Komponente bereitgestellten Methoden also nicht direkt, sondern nur über die Fassadenschnittstelle aufgerufen (s. Abbildung). Die Fassade stellt demnach eine Art einheitlich Programmierschnittstelle für die gekapselte Komponente dar.
Befassen wir uns zum Schluss mit dem Wrapper-Muster. Anders als die drei bereits vorgestellten Muster ist es nicht Teil des Musterkataloges der Gang of Four, sondern wird unter anderem von Schmidt et al. (2010) beschrieben. Ein Wrapper kommt zum Einsatz, wenn der Zugriff von außen auf Klassen einer Komponente besonders kompliziert ist. Die Komplexität lässt sich dann in einer einzelnen Methode eines Wrappers kapseln, die dann alle erforderlichen Komponenten-internen Aufrufe steuert. Anstatt die Klassen einer Komponente also einzeln nacheinander aufzurufen, wird diese Aufgabe an den Wrapper delegiert (s. Abbildung). Der Wrapper ähnelt stark der Fassade, unterscheidet sich aber in zwei Aspekten: Erstens kann es im Gegensatz zur Fassade durchaus mehr als einen Wrapper pro Komponente geben. Zweitens enthält eine Fassade im Gegensatz zum Wrapper definitionsgemäß keine Logik im Sinne der geordneten Bündelung von Methodenaufrufen.
Zum Schluss alle wichtigen Unterscheidungsmerkmale auf einen Blick:
Muster | Adapter | Dekorierer | Fassade | Wrapper |
Problem: | … löst Inkompatibilitäten auf. | … fügt Funktionalität hinzu. | … bündelt Schnittstellen. | … bündelt Schnittstellenaufrufe. |
Prinzip: | Verbindet zwei bestehende (!), inkompatible Klassen/Komponenten | Erweitert bestehende Klasse um zusätzliche Funktionalität (ohne Vererbung) | Klassen einer Komponente sollen nur über eine einheitliche Schnittstelle zugänglich sein. | Kapselt nach außen komplizierte Aufrufe von Klassen einer Komponente |
Literatur
- Gamma, E., Helm, R., Johnson, R., Vlissides, J.: “Entwurfsmuster: Elemente wieder verwendbarer objektorientierter Software“. Addison-Wesley. 2009. ISBN 978-3-8273-2824-3
- Schmidt, D., Stal, M., Rohnert, H., Buschmann, F.: “Pattern-Oriented Software Architecture: Patterns for Concurrent and Networked Objects”. Wiley. 2000. ISBN 978-1-118-72517-7
- Eilebrecht, K., Starke, G.: “Patterns kompakt: Entwurfsmuster für effektive Software-Entwicklung“. Springer Vieweg. 2013. ISBN: 978-3-642-34717-7