5. Wiederverwendung im Softwareentwurf 5.1 Entwurfsmuster .KVGTCVWT Gamma/Helm/Johnson/Vlissides: Design Patterns, Addison-Wesley 1994 (= „Gang of Four“, „GoF“) Buschmann/Meunier/Rohnert/Sommerlad/Stal: A System of Patterns, Wiley 1996 Vlissides: Pattern Hatching, Addison-Wesley 1998 Grand: Patterns in Java, 2 Bde, Wiley 1998, 1999 Cooper: Java Design Patterns - A Tutorial, Addison-Wesley 2000 Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Klassifikation von Mustern Muster ... ModellierungsMuster Universelle Muster Analysemuster VorgehensMuster Phasenspezifische Muster Architekturmuster Erzeugung Technische Universität Dresden OrganisationsMuster Entwurfsmuster Struktur Prof. Hußmann Seite 1 SprachIdiome Verhalten Softwaretechnologie II Muster verstehen • Musterkataloge: – „langweilig“ – „Alle Muster sehen fast gleich aus.“ • Muster verstehen heißt Muster im Anwendungskontext zu erkennen. • Jedes Muster entspricht der Entwurfsentscheidung, bestimmte Aspekte variabel (flexibel) zu halten. • Online-Ressourcen zum Finden von Patterns (im Aufbau): – Pattern Stories: http://st-www.cs.uiuc.edu/cgi-bin/wikic/wikic – Pattern Depot (Addison-Wesley): http://www.patterndepot.com – Portland Pattern Repository: http://c2.com/ Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Erzeugungsmuster (nach „Gang of Four“) • Mustername: variabel gemachter Aspekt • • • • • Implementierungsvarianten Familien von Implementierungsvarianten Repräsentation komplexer Objekte Repräsentation komplexer Objekte globaler Konstruktorzugriff mit Sicherstellung, daß genau eine Instanz erzeugt wird Factory Method: Abstract Factory: Builder: Prototype: Singleton: Technische Universität Dresden Prof. Hußmann Seite 2 Softwaretechnologie II Strukturmuster (nach „Gang of Four“) • Mustername: variabel gemachter Aspekt • • • • • • • Schnittstelle zu konkretem Objekt Implementierung eines Objekts Objektstruktur eines komplexen Objekts Verantwortlichkeiten Schnittstelle eines Teilsystems Speicheraufwand für ein Objekt Zugang zu einem Objekt und Ort eines Objekts Adapter: Bridge: Composite: Decorator: Facade: Flyweight: Proxy: Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Verhaltensmuster (nach „Gang of Four“) • Mustername: variabel gemachter Aspekt • • • • • • • • • • • Objektkopplung Konstruktion von Methodenaufrufen Abstraktionsebene Durchlauf(reihenfolge) bei Kollektionen Objektkopplung Reversibilität Objektkopplung (Zustandsveränderungen) zustandsabhängiges Verhalten Algorithmenverwendung Verwendung von Funktionsbausteinen Durchlauf komplexer Objektstrukturen Chain of Responsibility: Command: Interpreter: Iterator: Mediator: Memento: Observer: State: Strategy: Template Method: Visitor: Technische Universität Dresden Prof. Hußmann Seite 3 Softwaretechnologie II Dateisystem-API: Grundlagen • Beispiel zur Anwendung von verschiedenen Mustern – flexible Zugriffsschicht auf Dateisysteme – Quelle: Vlissides 98 • Grundlegende Einheiten: – Elementare Dateien – Verzeichnisse (directories) • Gemeinsame Operationen auf Dateien und Verzeichnissen: – Name, Größe, Zugriffsrechte, ... Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Entwurfsmuster Composite • Strukturmuster • Problem: Hierarchische Struktur von Objekten • Lösung: Einheitliche abstrakte Schnittstelle für „Blätter“ und Verzweigungsknoten eines Baumes Component {abstract} operation() getChildren() * Leaf Composite operation() getChildren() operation() getChildren() Technische Universität Dresden Prof. Hußmann Seite 4 Softwaretechnologie II Zugriff auf Unterstrukturen • Operationen auf Unterstrukturen (operation()): – Beispiel: Directory-Listing (ls, dir), auch rekursiv – Durchlaufen der Elemente einer Kollektion – Reihenfolge » i.a. nicht wesentlich » in speziellen Fällen relevant • Problem: – Verallgemeinerung einer for-Schleife Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Entwurfsmuster Iterator (Enumeration) • Verhaltensmuster • Problem: Aggregate (z.B. Listen, Mengen, Bäume) müssen oft vollständig durchlaufen werden. Dabei soll die konkrete Realisierung des Aggregats nicht festgelegt werden. • Lösung: Interface oder Abstrakte Klasse für Zugriffsschnittstelle. Aggregate {abstract} Iterator {abstract} createIterator(): Iterator next(): Element {abstract} isDone():boolean {abstract} {abstract} <<create>> ConcreteAggregate ConcreteIterator 1 * Element Technische Universität Dresden Prof. Hußmann Seite 5 Softwaretechnologie II Aliasse • Datei-Alias – „symbolic link“ in Unix – „alias“ in MacOs – „shortcut“ in Windows 95+ • Operationen auf Dateien und Aliassen – Alias erlaubt alle Operationen, die auf Originalen möglich sind – Fast immer: Weiterleitung von Operationen an das Original – Spezielle Interpretation z.B. für Löschoperation Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Entwurfsmuster Proxy • Strukturmuster • Problem: Der direkte Zugriff auf ein Objekt ist problematisch. (z.B. großer Aufwand, Sicherheitsprobleme) • Lösung: Stellvertreter-Objekt Subject <<use>> Client request() ConcreteSubject original request() Technische Universität Dresden Proxy request() Prof. Hußmann Seite 6 Softwaretechnologie II Composite + Proxy Node {abstract} Proxy original getName() getProtection() getChildren() read() write() add() remove() Link File Composite * Directory getName() getName() getName() * getProtection() getProtection() getProtection() getChildren() getChildren() getChildren() read() read() read() write() write() write() add() add() add() remove() remove() remove() Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Dateien durchlaufen • Allgemeine Operationen auf Dateien: Worte zählen, UNIX „cat“ • Operation von „Node“? – praktisch alle Klassen müssen verändert werden ! • Offene Schnittstelle von „Node“ – beliebige Operationen für „Besucher“ • Entwurfsmuster „Visitor“: – Erklärt im GoF-Buch für Syntaxanalyse... Technische Universität Dresden Prof. Hußmann Seite 7 Softwaretechnologie II Entwurfsmuster Visitor • Verhaltensmuster • Problem: Operationen auf einer komplexen Objektstruktur sollen leicht veränderbar bleiben, ohne die Struktur selbst zu verändern • Lösung: Standard-Schnittstelle für „Besucher“ <<interface>> Visitor Element visitA(e: ConcreteElementA) visitB(e: ConcreteElementB) accept(v:Visitor) ConcreteElementA ConcreteVisitor1 accept(v:Visitor) v.visitA(this) ConcreteVisitor2 ConcreteElementB accept(v:Visitor) Technische Universität Dresden v.visitB(this) Prof. Hußmann Softwaretechnologie II Beispiel: Visitor-Muster (1) abstract class Node { ... abstract void accept (NodeVisitor v); ...} class File extends Node { ... void accept (NodeVisitor v) { v.visit(this) } …} class Directory extends Node { ... void accept (NodeVisitor v) { v.visit(this) } …} class Link extends Node { ... void accept (NodeVisitor v) { v.visit(this) } …} interface NodeVisitor { void visit (File f); void visit (Directory d); void visit (Link l); } Technische Universität Dresden Prof. Hußmann Seite 8 Softwaretechnologie II Beispiel: Visitor-Muster (2) class WordCtVisitor implements NodeVisitor { void visit (File e) { Code zum Zählen der Worte } void visit (Directory e) { Schleife über alle Kinder } void visit (Link e) { original.accept(this) } } • Alle Besucher implementieren das „Visitor“-Interface. • Verschiedene Besucher, z.B. WordCtVisitor, CatVisitor realisieren konkrete Operationen auf der besuchten Struktur. • Besucher sind flexibel konfigurierbar. – Durchlaufstrategie im Visitor beschrieben Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Schutz gegen versehentliches Überschreiben • Operation zum Überschreiben von Datei / Verzeichnis / Link: – unveränderlicher Anteil für alle Knoten » Schreibvorgang » Grundsätzliche Logik – unterschiedlicher Anteil je nach Unterklasse » genaue Kriterien für Zulässigkeit » spezielle Fehlermeldung • Beispiel: – aDirectory.write(x) liefert immer Fehlermeldung „directory can‘t be written“ – aFile.write(x) prüft lokale Zugriffsrechte und gibt ggf. Fehlermeldung „file is read-only“ Technische Universität Dresden Prof. Hußmann Seite 9 Softwaretechnologie II Entwurfsmuster Template Method • Verhaltensmuster • Problem: Operation besteht aus festen und veränderlichen Bestandteilen • Lösung: Schablonenmethode in Oberklasse mit Aufruf abstrakter Einschubmethoden, die in Unterklassen überdefiniert werden. AbstractClass {abstract} method1 {abstract} method2 {abstract} method3 method3 () { ...; ...; method1(); ...; ...; method2(); } ConcreteClass method1 method2 Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Beispiel Node {abstract} getName() getChildren() read() write() isWritable() writeError() Link * getName() getChildren() read() write() isWritable() reportError() Technische Universität Dresden File * if (isWriteable()) { ...} else reportError() Directory getName() getName() getChildren() getChildren() read() read() write() write() isWritable() isWritable() reportError() reportError() Prof. Hußmann Seite 10 Softwaretechnologie II Benutzer in einem Mehrbenutzersystem • Benutzer loggen sich in das System ein. – Erzeugung eines Objekts der Klasse UserSession • Wir wollen sicherstellen, daß – nur eine maximale Anzahl von Benutzersitzungen je Benutzer besteht – UserSessions nur erzeugt werden, wenn die Authentisierrung erfolgreich war • Grundidee: – Singleton-Muster – Variation nötig Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Entwurfsmuster Singleton • Erzeugungsmuster • Problem: Manche Klassen sind nur sinnvoll, wenn sichergestellt ist, daß immer höchstens eine Instanz der Klasse besteht (und diese bei Bedarf erzeugt wird). • Lösung: – Modellebene: – Programmebene: Klassen als Singleton auszeichnen Sprachabhängig • Beispiel (Java): class Singleton { private static Singleton theInstance; private Singleton () { } public static Singleton getInstance() { if (theInstance==null) theInstance = new Singleton(); return theInstance; } } Technische Universität Dresden Prof. Hußmann Seite 11 Softwaretechnologie II Entwurfsmuster Singleton (erweitert) • Die "getInstance()" Methode kann kompliziertere Tests ausführen als nur auf Existenz eines Objekts: • Beispiel: class UserSession { private static Map userSessions; private UserSession () { } public static UserSession createUserSession(String login) { if ( Anzahl von Sessions für login < max ) { if ( Identifikation(login) ) { UserSession u = new UserSession(); userSessions.add(login,u); return u; } else return null; //evtl. Fehlermeldung } else return null; //evtl. Fehlermeldung } } Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Weitere Entwurfsmuster für das Beispiel • Zusammenfassung von Benutzern zu Gruppen: – Mediator • Zusammengefasste Schnittstelle des gesamten Dateisystems: – Facade • Kommandosprache: – Command, Interpreter • Undo-Operationen: – Memento • Abbildung auf unterliegende Systemschichten: – Adapter • Schutzmechanismen für Dateioperationen: – State Technische Universität Dresden Prof. Hußmann Seite 12 Softwaretechnologie II Entwurfsmuster (Objekt-)Adapter • Strukturmuster • Problem: Ein aufrufendes Objekt (Client) erwartet eine andere Schnittstelle, als sie von einem anbietenden Objekt bereitgestellt wird. • Lösung: "Adapter" zur Umsetzung der Schnittstellen. (Bei Einbindung von Altsystemen auch "Wrapper" genannt.) Client Target {abstract} Adaptee request specificRequest adaptee ruft adaptee.specificRequest auf Adapter request Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Entwurfsmuster Memento • Verhaltensmuster • Problem: Zustand eines Objektes muß gespeichert werden, z.B. für "undo"-Operationen. • Lösung: "Memento"-Objekt speichert Zustand, "Caretaker"-Objekt verwaltet verschiedene Mementos. Caretaker :Caretaker :Subject createMemento * Memento state setState getState result = m <<creates>> setMemento(m) Subject new m:Memento setState getState state setMemento createMemento Technische Universität Dresden Prof. Hußmann Seite 13 Softwaretechnologie II Weitere Entwurfsmuster (nicht „GoF“) • Weiterentwicklung von Mustern: – Pattern Community – Pattern Languages – Pattern Repositories • Reifeprozeß eines Musters: – – – – – Vorschlag unabhängige Anwendungsberichte Aufnahme in Lehrbücher Werkzeugunterstützung Mustersystematik » Klassifikation » Generalisierung, Spezialisierung » Anwendungsbereichsspezifische Mustersprachen Technische Universität Dresden Prof. Hußmann Softwaretechnologie II Entwurfs-Antimuster "Law of Demeter" • "Law of Demeter" (1988) – Demeter-Projekt: Smalltalk-orientiert, Kriterien für Strukturqualität – http://www.ccs.neu.edu/home/lieber/LoD.html • Regel kann man als Entwurfs-Antimuster verstehen: – Ein Objekt A sollte keine Operationen eines Objektes C aufrufen, das indirekt über Operationen einer Klasse B bestimmt wurde. – „Don't talk to strangers.“ • Beispiel (unerwünscht!): 2: gib Betrag 1: gib Buchungen Kontoauszug Konto 0..* 1 + service ... Technische Universität Dresden Buchung 1 Prof. Hußmann Seite 14 0..* + service ... Softwaretechnologie II Entwurfsmuster Callback • Verhaltensmuster zur Realisierung von Ablaufsteuerung • Problem: Ein Objekt A beauftragt ein anderes Objekt B mit der Abwicklung eines Unterauftrags und will festlegen, wie das Ergebnis mitgeteilt wird. • Lösung: A teilt B mit, welcher Methodenaufruf (von A) bei Fertigstellung auszuführen ist. 1: service (callback) Client Supplier 2: callback(result) + callback ... Technische Universität Dresden + service ... Prof. Hußmann Softwaretechnologie II Entwurfsmuster Client-Dispatcher- Server • Verhaltensmuster zur Realisierung von Verteilung • Problem: Ein Objekt A möchte ein anderes Objekt B mit der Abwicklung eines Unterauftrags beauftragen, weiß aber nicht, wie ein geeignetes B-Objekt zu finden ist. • Lösung: Verwendung eines "Dispatcher"-Objektes, das die Aufträge von Client-Objekten an Server-Objekte weiterreicht. Client 1: service Dispatcher + service ... Technische Universität Dresden Prof. Hußmann Seite 15 2: service Supplier + service ... Softwaretechnologie II Entwurfsmuster Manager • Strukturmuster • Problem: Client-Objekte benötigen Information, die sich auf die Gesamtheit aller vorhandenen Objekte einer Subject-Klasse beziehen. • Lösung: Einführung einer Manager-Klasse Manager Subject <<use>> Client 0..* create search remove Technische Universität Dresden service Prof. Hußmann Softwaretechnologie II Entwurfsmuster HOPP (Half-Object Plus Protocol) • Verhaltensmuster zur Realisierung von verteilten Anwendungen • Problem: Ein Objekt wird in zwei Adreßräumen benötigt (d.h. ist global für zwei Knoten). • Lösung: Je ein "Halb-Objekt" auf den beiden beteiligten Knoten sowie ein Synchonisationsprotokoll. Whole {abstract} + service 1 {abstract} + service 2 {abstract} Knoten 1 Knoten 2 Half 1 Client 1 + service 1 + service 2 – service_impl 1 + synchronize Technische Universität Dresden 1 1 Protocol Prof. Hußmann Seite 16 Half 2 + service 1 + service 2 – service_impl 2 + synchronize Client 2 Softwaretechnologie II