Decorator Pattern Analyse- und Design-Pattern CAS SWE FS14 Roland Müller Samuel Schärer Entwurfsmuster der «Gang of Four» ◦ Strukturmuster fassen Klassen und Objekte zu grösseren Strukturen zusammen Adapter Bridge Decorator Facade Composite … Klassifikation 2 Kaffee-Sorten ◦ Arabica ◦ Koffeinfrei Kaffee-Zusätze ◦ Zucker ◦ Milch Beispiel Kaffeebar 3 Varianten 4 2 zusätzliche Kaffee-Sorten: Erweiterungen 5 2 zusätzliche Kaffee-Zusätze: Erweiterungen 6 Erweiterungen sind Aufwändig und Fehleranfällig ◦ Pro neuer Zusatz müssen 4 neue Klassen erstellt werden ◦ Wenn sich der Preis einer Sorte ändert müssen alle Klassen mit dieser Sorte angepasst werden Keine Flexibilität ◦ Es sind nur die fix modellierten Kombinationen möglich Mangelnde Dynamik ◦ Keine Möglichkeit während der Laufzeit dynamisch Zusätze hinzuzufügen oder zu entfernen Nachteile 7 Die Funktionalität von Objekten dynamisch erweitern, ohne dabei deren Klasse zu verändern Decotator-Zweck 8 Die Kaffee-Sorten sowie die Kaffee-Zusätze bleiben konstant Kaffee-Sorten Kaffee-Zusätze Variabel sind die Kombinationen aus Kaffee-Sorte und den verschiedenen Zusätzen Decorator-Prinzip 9 Eine Kaffee-Sorte mit beliebigen Zusätzen umhüllen (dekorieren) Arabica Milch Zucker Decorator-Idee 10 Aufgaben von innen nach aussen erledigen Arabica getPreis() getPreis() getPreis() 3.0 Milch +0.5 +0.5 +0.1 3.60 Zucker Decorator-Idee 11 Konkrete Sorten Konkrete Zusätze Modell (Beispiel Kaffee) 12 Konkrete Sorten public interface Kaffee { public double getPreis(); public void druckeBeschreibung(); } Konkrete Zusätze Implementierung 13 Konkrete Sorten public class Arabica implements Kaffee { public void druckeBeschreibung() { System.out.print("Arabica"); } public double getPreis() { return 3.00; } } Konkrete Konkrete Zusätze Zusätze Implementierung 14 Konkrete Sorten public abstract class Zusatz implements Kaffee { protected Kaffee kaffee; public Zusatz(Kaffee kaffee) { this.kaffee = kaffee; } } Konkrete Konkrete Zusätze Zusätze Implementierung 15 public class Milch extends Zusatz { public Milch(Kaffee kaffee) { Konkrete Sorten super(kaffee); } public void druckeBeschreibung() { kaffee.druckeBeschreibung(); System.out.print(", Milch"); } public double getPreis() { return kaffee.getPreis() + 0.50; } } Konkrete Konkrete Zusätze Zusätze Implementierung 16 public class Zucker extends Zusatz { public Zucker(Kaffee kaffee) { Konkrete Sorten super(kaffee); } public void druckeBeschreibung() { kaffee.druckeBeschreibung(); System.out.print(", Zucker"); } public double getPreis() { return kaffee.getPreis() + 0.10; } } Konkrete Konkrete Zusätze Zusätze Implementierung 17 public class Kaffeebar { public static void main(String[] args) { Kaffee meinKaffee = new Zucker(new Milch(new Arabica())); meinKaffee.druckeBeschreibung(); // Arabica, Milch, Zucker System.out.println("Preis: CHF "+ meinKaffee.getPreis()); // Preis: CHF 3.60 } } Verwendung Arabica Milch Zucker 18 Modell (Allgemein) 19 Wenn bereits Code existiert, den man mit geringem Aufwand so anpassen möchte, dass später Klassen einfach erweitert werden können Wenn man verhindern will, dass durch allfällige Erweiterungen zu viele Subklassen entstehen Wenn man zur Laufzeit Status oder Verhalten einer Klasse erweitern und beliebig kombinieren will Wenn man Klassen erweitern oder hinzufügen will ohne dass andere Klassen davon betroffen sind (Open/Closed Prinzip) Wann sollte das Decorator Pattern in Erwägung gezogen werden? Wenn ein dynamisches Erweitern einer Komponente nicht erforderlich ist, sind ev. Subklassen besser geeignet Höhere Komplexität als mit Subklassen Die oft langen Aufrufketten erschweren das Finden von Fehlern und führen zu unübersichtlichem Initialisierungscode Objekt-Vergleiche können Fehler verursachen Dekorierte Komponenten sind als Objekt nicht identisch Was spricht gegen das Decorator Pattern? 21 Adapter/Wrapper ◦ Wenn ein Interface zwischen zwei Klassen (ohne zusätzliche Funktionalität) ausreicht Composite ◦ Wenn es darum geht eine Hierarchie abzubilden (wie z.B. Filesystem) Proxy ◦ Wenn es darum geht Zugriffsberechtigungen auf Objekte zu steuern Strategy ◦ Wenn das Original Objekt geändert werden soll anstatt nur Zugriff zu gewähren Wann sollten verwandte Pattern in Betracht gezogen werden? Java Swing JScrollPane Anwendungsbeispiele Java IO Anwendungsbeispiele Fragen? 25