# FAQ Kap 24 - Design Patterns for Product Lines * Kap 24 ist SEHR klausurrelevant. Bitte ernstnehmen. * Dagegen ist Kapitel 25 das "Königskapitel" von Teil 2. Es ist nur klausurrelevant in Bezug auf die Patterns Fabrikmethode und Command. Aber es zeigt alle Entwurfsmuster im Konzert, im Rahmen einer großen Graphbibliothek, jgrapht, die von einer sehr aktiven Community entwickelt wird. * Graphen und Graphbibliotheken sind aber wichtig für Ihre Zukunft, denn sie kann man vielfältig einsetzen. * jgrapht verwendet sehr viele Entwurfsmuster, und wenn man wissen will, wie große Frameworks Entwurfsmuster verwenden, sollte man es studieren. ## Variability Patterns ### Template Method and Template Class * Können Sie bitte den Unterschied zwischen Template Class und Template Mixin erklären? * Die Absicht des Musters ist unterschiedlich. Mixins sind Unterobjekte, die mit dem Kernobjekt "sterben", d.h. nicht alleine lebensfähig sind. Das ist i.d.R. bei TemplateClass nicht so, da darf das Unterobjekt (Hook) "entkommen" oder alleine leben nach dem Tod des Template-Objekts. * Das TemplateMixin eine spezielle Art von TemplateClass, weil der Pfeil von Template zu Hook eine schwarze Raute benutzt ("composite" Relation anstatt "has-a"). Diese Raute drückt gerade die gleichzeitige Lebenszeit aus. #### Strategy vs. Template Class * Noch einmal zu dem Unterschied von Strategy und Template Method. Gibt es eine treffsichere Methode, die zu unterscheiden? * Die Intention (intent) der Muster ist leicht unterschiedlich: * Strategy (stammt aus dem Gamma) variiert einen Algorithmus, d.h. eine Methode in einem Hauptobjekt, die einen Algorithmus ausführt. (Siehe Formatter-Beispiel) * TemplateClass (kommt im Gamma nicht vor) variiert eine Methode eines Hauptobjektes, die irgendeine Art von domänenspezifischer Aktivität ausführt. Die Intention ist also leicht anders und allgemeiner. * Strukturell sind die beiden Muster aber identisch, und drücken Variabilität aus. * Warum das Gamma-Buch die Strategy so eng definierte, ist unklar, und historisch bedingt. * Das TemplateClass-Muster, wie auch Strategy, kann während der Laufzeit verändert werden, indem man das Hook-Objekt austauscht. Die Referenzen auf das Hauptobjekt verbleiben gültig. * Bei einem TemplateMethod-Objekt kann man nur zur Allokationszeit die genaue Unterklasse festlegen. Wenn man Referenzen auf das Objekt ausgegeben hat, entstehen "dangling references", wenn man das Objekt polymorph variiert, und der Programmierer muss diese "dangling references" in den client-Objekten ändern. Das ist sehr fehleranfällig, i.G. zu TemplateClass, denn da bleiben die Referenzen ja gültig. ### Abstract Factory (Factory Class) * Abstract Factory ist also in der Anwendung ähnlich zu Strategy, nur mit Klassen und nicht nur Funktionen? * Man kann sagen, dass Abstract Factory eine Art Strategiemuster ist für die Allokation von Objektfamilien mit Objekten (A, B, C, ..) in Varianten (1, 2, 3, ...) bzw. bestimmten Farben. * Variiert wird das Fabrikobjekt, das von seiner Aktivierung an bestimmt, welche Objektfamilie (1,2,3..) alloziert wird, bzw. welche "Farbe" die Objekte haben. ### Brücke (Bridge) * Wenn man also eine abstrakte Klasse hat und eine konkrete Klasse, die von dieser abstrakten Klasse erbt, habe ich dann schon eine Brücke? * Nein, das würde nur die linke Hierarchie (Abstraktum) betreffen; die Brücke besteht aus zu wei gekoppelten Hierarchien, Abstraktum und Implementation. Ersteres kapselt die plattformunabhängige, implementierungsunabhängige Information. Letzteres kapselt plattformabhängige, implementationsspezifische Informationen. * Gibt es dann nicht Composite Varianten die Brücken sind? * Das Mischen von Composite und Brücken ist möglich. Dann würde jedes Objekt im Baum ein privates "Implementation-Objekt" haben. Vielleicht braucht es einen Namen für diese Mustervariante: Hierarchic Bridge? * Aber wie überlebt das Implementation-Objekt, wenn die ConcreteAbstraction deallokiert wird? Wenn sie noch von anderen ConcreteAbstractions genutzt wird? * Ja, das ist die Semantik der "weißen Raute" im Brücken-Pfeil. Sonst müsste es eine schwarze Raute sein. * Wenn das Implementation-Objekt überleben soll, muss man einen Zeiger auf es herausgeben, z.B. durch einen Return einer Methode "getImplementationObject()". ## Extensibility Patterns ### Decorator * Kann ein Dekorator nur einen Nachfolger haben oder auch mehrere? * Nur einen, denn es gibt eine Dekorator-Liste um das reale Objekt herum. * Hier unterscheiden sich Composite und Decorator, denn ersteres Muster erlaubt viele Nachfolger eines Objekts und damit insgesamt Baumstrukturen. Vergleiche dazu die Strukturdiagramme. ### Visitor * Was macht ein Visitor? Wozu braucht man den? * Ist der Visitor nicht sehr änhlich dem Bridge-Pattern? * Ja, aber die Datenstruktur nimmt ein Visitorobjekt als Parameter, dh. es ist außen sichtbar. In der Bridge ist das Hookobjekt außen unsichtbar. * Man kann sich natürlich ein Misch von Bridge und Visitor vorstellen, in dem dem Abstraktum gesagt wird, welche Implementation-Variante es ausführen soll. * Spielt es dabei eine Rolle, ob die Datenstruktur dabei verändert wird? * Visitorobjekte können ohne Probleme Attribute von Datenstrukturobjekten ändern. * Aber Vorsicht ist geboten, wenn sie die Zeiger der Datenstruktur, ihre Vernetzung, ändern: in der Regel sind Visitor-Algorithmen rekursiv auf der Datenstruktur, und wenn man die Vernetzung ändert, gibt es Seiteneffekte auf die Rekursion. ### Singleton * Mir fällt es schwer, mir den Nutzen zum Singleton vorzustellen. Haben Sie dafür ein Beispiel? * Einsatzzwecke des Singletons: Das Singleton kann globales Konfigurationswissen der Anwendung speichern, z.B. die Parameter von main(). * Man kann Singleton z.B. als so einer Art Cache für die Multi-Threaded Programme verwenden, um zu sichern, dass alle Daten im gleichen Ort gespeichert werden. Allerdings ist das Schreiben auf den Attributen des Singletons dann zu synchronisieren (mit "synchronize" methods) * Außerdem, wenn man sich vorstellt, dass der Singleton für Global State sein soll, explodiert da nicht die "Größe" des Singletons? * Ja, das kann passieren, ist aber in der Regel kein Problem, da man das Singleton auf mehrere Klassen/Singletons aufteilen kann. * Im OPAL-Fragebogen zu den Entwurfsmustern wird das Singleton als Anti-Pattern bezeichnet, wieso ist das so bzw. was sind die Nachteile des Pattern? * Singleton kommt aus dem Gamma und wird benutzt, um globale Konfigurationseinstellungen, z.B. die Array-Parameter der Kommandozeile, zu speichern. * In C++ wird das über globale Variablen gemacht, die bei paralleler Programmierung gefährlich sind, denn sie erzeugen Zugriffskonflikte beim Schreiben ("race conditions", "write conflicts"). Race conditions sind extrem hart zu debuggen, weshalb man lieber keine globalen Variablen nutzt. * Aber: will. man ein C++-Programm auf Java umstellen, muss man alle globalen Variablen erst mal auf ein Singleton umstellen, und ggf. die Methoden durch den Modifier "synchronize" gegen write-Konflikte schützen. * Das Singleton verstößt im Prinzip gegen das Class-Single-Responsibility-Principle, denn i.d.R. sollen Attribute zu einem Objekt gehören, zu denen es auch *semantisch* gehört (responsibility). Siehe CRC-Methode! Also sollte man auf jeden Fall vermeiden, das Singleton zu groß zu gestalten. * Aber: auch Algorithmenklassen und alle komplexen Objekte wie Bridge oder TemplateClass-Objekte verstoßen gegen das Class-Single-Responsibility-Principle! denn sie teilen eine "logisch zusammengehörende Klasse" auf mehrere Implementierungsklassen auf. * Letztlich sind das alles "Kräfte/forces", die auf das Design einwirken und individuelle Design-Entscheidungen verursachen (die Sie dokumentieren sollten). ### Observer * Wann braucht man bei push und pull nur einen Observer und wann braucht man mehrere? * Callbacks sind im Programmieren sehr häufig, wenn man asynchron oder verteilt programmiert. Man setzt sie ein, wenn man weiß, man hat nur *einen* Observer. * Push oder pull entscheidet sich daran, wie groß die Datenstruktur ist, die man aus dem Subjekt zum Observer transportieren muss. Ist sie klein, funktioniert Push prima. Ist sie groß, z.B. ein Bild oder ein Video, überlässt man die Initiierung des Transports dem Observer. ## Glue Patterns ### Adapter * Wie wichtig ist das Adapter-Muster? * Adapter sind eines der am Häufigsten eingesetzten Muster, zwischen Neu- und Alt-komponenten. ##Überblick * Mir fallen immer wieder Parallelen zwischen verschiedenen Entwurfsmustern auf. Könnten wir vllt eine kleine Übersicht erstellen, welche Muster auf anderen Mustern aufbauen? Sozusagen als Baumdiagram oder so? * Leider sind alle Versuche, Entwurfsmuster in eine Vererbungshierarchie zu bringen, gescheitert. Die Einteilung in Variabilitäts-, Erweiterungs- und KLebemuster ist schon umstritten, obwohl sinnvoll. * Oder vllt eine kleine "Landkarte", was mehr oder weniger zusammenhängt * siehe Kapitel 24, Folie 65 "Relations between Design Patterns". * was ist Visitor? ##Weitere Fragen * Was sind SOLID-Prinzipien? Und kann man sagen, dass diese auch Design patterns sind? * die SOLID-Prinzipien https://en.wikipedia.org/wiki/SOLID bilden keine Entwurfsmuster, sondern Architekturprinzipien. Ein Entwurfsmuster hat immer einen Strukturellen Kern, den man in der Software wiederfinden kann. SOLID-Prinzipien sind Entwurfsprinzipien, die keine direkte Strukturentsprechung haben: * **Single** responsibility for a class * **Open**-closed (open for extensions) * **Liskov** substitution principle: Die Ersetzbarkeit von Objekten der Oberklassen druch Unterklassen (siehe Abschnitt III) * **Interface** segregation: kleine Schnittstellen, bitte * **Dependency** inversion: Abstraktionen sollten nicht von Details abhängen