Group of Four - Patterns!

Group of Four - Patterns!

In eigenem Fenster öffnen

Design Patterns - Inhalt

Erzeugungsmuster
Strukturmuster
Verhaltensmuster
Kurzfassung

Erzeugungsmuster

Abstract Factory, ToolKit (Abstrakte Fabrik)

Der Klient soll gewisse Objekte benutzen, aber ihre Klassen nicht kennen. Um sie zu erzeugen benutzt er eine Fabrik, welche eine Schnittstelle bietet, um die (dahinter verborgene) Objekte zu erzeugen. Durch Austausch der Fabrik können andere Objekte erzeugt werden.

Bsp: WidgetFabriken erzeugen unterschiedliche Look-and-Feel-Standards (GUI)

Builder (Erbauer)

Man trennt die Berechnungen/Konstruktion (Director) von der Präsentation (Builder), wodurch bei gleicher Berechnung leicht unterschiedliche Präsentationen gewählt werden können.

Bsp: RTF-Loader und RTF-Konvertierer (wovon es dann unterschiedliche gibt)

Factory Method, Virtual Constructor (Fabrikmethode)

Eine (bis dahin abstrakte) Anwendung benötigt ein (bis dahin abstraktes) Objekt, also was sie nicht direkt erzeugen kann (da abstrakt) obwohl sie muss. Sie benutzt eine Methode, die ein solches Objekt erzeugt. Die spätere nicht-abstrakte Anwendung überschreibt die Methode und erzeugt das konkrete Objekt.

Bsp: Editor und Dokument: Dok = AbstraktEditor.CreateDoc

Prototype (Prototyp)

Ein Erzeuger soll Objekte erzeugen, von denen er nur eine Basisklasse kennt, sprich konkrete Klasse unbekannt. Eine Clone-Fkt. in dieser Basisklasse (Prototyp) erzeugt eine Kopie des Objekts. Jeder Erzeuger erhält bei Initialisierung ein fertiges Objekt von der Klasse, von der er Objekte erzeugen soll und dies mittels der Clone-Fkt dann auch tun kann ohne die Klasse zu kennen.

Bsp: Grafisches Werkzeug (Erzeuger) zur Darstellung grafischer Objekte. Es reicht eine Werkzeugklasse, die mit dem Prototyp umgehen kann. Pro grafisches Objekt (bzw. Klasse) wird ein Werkzeug-Objekt mit entsprechender Initialisierung erstellt.

Singleton

Garantiert, dass nur ein Objekt von diesem Typ erzeugt wird. Dazu muss der Konstruktor privat sein, ebenso muss es eine private Klassenvariable des eigenen Typs geben und eine öffentliche Klassenmethode für den Zugriff (und gegebenenfalls Erzeugung)

Bsp:

class Singleton { 

private: 
  static Singleton* expl = 0; //Klassenvariable (einmalig pro Klasse) 

protected: 
  Singleton() {}; //privater Konstruktor verhindert Erzeugung von außen 

public: 
  static Singleton* Exemplar() 
    {  //Klassenmethode, die Singleton zurückgibt, bzw. einmalig erzeugt 
       if (expl==0) {expl=new Singleton()}; 
       return expl 
    } 
} 

Strukturmuster

Adapter, Wrapper

Es existiert bereits eine Klasse für eine spezielle Aufgabe, aber ihre Schnittstelle passt nicht zum Klienten. Ein Adapter bietet dem Klienten die passende Schnittstelle, benutzt intern jedoch für die Funktionalität ein Objekt der vorhandenen Klasse. Alternativ könnte der Adapter auch über Mehrfachvererbung von beiden Schnittstellen abgeleitet sein.

Bsp: Zeicheneditor benutzt Hierarchie grafischer Objekte. In die Hierarchie wird ein Text-Adapter-Objekt eingefügt, welches ein vorhandenes TextTool benutzt.

Bridge, Handle, Body (Brücke)

Wenn eine Hierarchie aufgrund unterschiedlicher Implementierung auf jeder Ebene aufgespalten werden muss, macht es Sinn, Abstraktion und Implementierung zu trennen, um eine Abstraktionshierarchie und eine Implementierungshierarchie zu erzeugen.

Bsp: Eine Fensterhierarchie enthält unter BasisFenster ein IconFenster und TransientFenster. Für verschiedene Betriebssysteme (bzw. Implementierungen) müsste jedes dieser Fenster zerlegt werden in z.B. XIconFenster und PMIconFenster. Eine Brücke vermeidet dies, indem eine eigene FensterImplementierung-Hierarchie gebildet wird. D.h. eine (abstrakte) BasisImplementierung bietet alle Fktn, die die Fenster benötigen. Von der BasisImplementierung leiten sich dann die verschiedenen Implementierungen ab, die dann entsprechend der Plattform benutzt wird.

Decorator, Wrapper (Dekorierer)

Klassen sollen mehr Funktion erhalten, jedoch will man das Ableiten vermeiden, weil man wegen einer zusätzlichen Funktion alle Klassen ableiten müsste. Um ein Objekt mit neuen Funktionen auszustatten, wird ein Dekorierer eingesetzt, welcher das Objekt aggregiert. Der Dekorierer ist vom gleichen Basistyp, bietet also dieselbe Schnittstelle. Allerdings reicht er alles an das Objekt weiter kann aber dabei zusätzliche Funktionen ausführen. Durch Schachtelung von Dekorierern kann einem Objekt unterschiedliche Funktionalität hinzugefügt werden.

Bsp: Eine TextAnzeige wird in einen Dekorierer für Scrollbalken gepackt und dieser in einen Dekorierer für Rahmen. Dadurch wird beim Zeichnen neben dem Text auch ein Scrollbalken und ein Rahmen angezeigt. Für den Klienten bleibt die Schnittstelle gleich.

Facade (Fassade)

Ein Subsystem bietet eine Vielfalt an Funktionalität und Klassenhierarchie. Für viele Anwender ist dies zu komplex, da mitunter nur wenig Funktionalität benötigt wird. Eine Fassade kapselt das Subsystem und fasst die wichtigste Funktionalität in einer Klasse zusammen (indem sie intern die benötigten SubKlassen aggregiert und unnötige Funktionalität ausblendet).

Bsp: Übersetzungssystem mit vielen Klassen. Eine Fassade "Übersetzer" mit der Funktionalität "Übersetzen()" sollte für die meisten Benutzer reichen.

Flyweight (Fliegengewicht)

Zu viele Objekten einer Klasse müssen erzeugt werden. Wenn es möglich ist, aus der Klasse kontextabhängige Informationen (extrinsisch) herauszunehmen und von einem KontextObjekt verwalten zu lassen, so enthält die Klasse nur noch kontextunabhängige (intrinsische) Informationen. Dann können Objekte, die sich bisher nur im Kontext unterschieden haben, durch ein einzelnes Objekt präsentiert werden. Statt mit vielen verschiedenen Objekten wird nun mit Referenzen auf gemeinsam genutzte Objekte gearbeitet. Methoden wird beim Aufruf die kontextabhängige Information mitgegeben.

Bsp: Ein Texteditor könnte pro Buchstabe im Text ein Objekt erzeugen mit Attributen Char + Pos. Zieht man das extrinsische Pos raus in ein Zeilen-Objekt, so enthält das Buchstaben-Objekt nur noch den intrinsischen Char. Statt ein Buchstaben-Objekt pro Buchstabe im Text muss nun nur noch ein Objekt pro Buchstabe im Alphabet erzeugt werden, und pro Buchstabe im Text gibts nur noch eine Referenz auf das entsprechende Objekt, also viel weniger Objekte. Der Zeichnen-Methode der Objekte wird die jeweilige Position vom Zeilen-Objekt mitgegeben.

Composite (Kompositum)

Einzelne Objekte sollen gruppiert werden und die Gruppe soll sich verhalten wie ein einzelnes Objekt, also u.a. wieder mit anderen Objekten/Gruppen gruppiert werden können. Für die Objekte existiert eine Basisklasse, und von dieser wird das Kompositum abgeleitet, wodurch es die gleiche Schnittstelle wie die Objekte hat und sich entsprechend verhält. Hinzu kommt aber, dass das Kompositum Objekte dieser Basisklasse aufnehmen kann. Ein Methodenaufruf wird von dem Kompositum an alle aggregierten Objekte weitergereicht.

Bsp: Gruppierung von Grafikkomponenten

Proxy, Surrogat

Ein Klient benutzt Objekte (Subjekt), welche z.B. lange Ladezeiten haben oder deren Zugriff kontrolliert werden muss. Ein Proxy wird dem Subjekt vorgeschalten, um eine schnellere Arbeit zu ermöglichen und erst dann einen Ladevorgang auszulösen, wenn dies wirklich notwendig ist. Der Ladevorgang wird hinausgezögert, indem kleinere Informationen über das Subjekt bereits im Proxy enthalten sind. Ist das Subjekt geladen, leitet der Proxy alle Anfragen weiter. Der Klient merkt nicht, ob er mit dem Proxy oder Subjekt direkt arbeitet, da das Proxy von der Basisklasse des Subjekts abstammt.

Bsp: Dokument mit vielen großen Bildern soll schnell geladen sein. Es reicht zunächst, wenn der Proxy Höhe und Breite zurückliefern kann.

Verhaltensmuster

Command, Action, Transaction (Befehl)

Befehle werden als Objekte gekapselt, die dann herumgereicht werden können. Der Aufrufer kennt mitunter den Empfänger nicht, aber er kennt die Basisklasse Befehl mit der Methode Execute. Der konkrete (abgeleitete) Befehl kennt dann den Empfänger und ruft dessen Methode Action auf. Parameter, Stapelung, Makrobefehle, Logbuch und Rückgängig wird dadurch möglich.

Bsp: Menü löst (konkreten) Klick-Befehl aus, der dann bei zugehöriger Objekt-Meth. landet.

Observer, Publish-Subscribe-Methode (Beobachter)

Die Änderung eines Objektes zieht die Änderung anderer Objekte nach sich. Um die Objekte nicht eng aneinander zu koppeln bietet der Observer die Möglichkeit, Änderungen eines Objektes an alle (angemeldeten) Beobachter weiterzumelden. Das geänderte Objekt braucht seine Beobachter also nicht zu kennen.

Bsp: Ein Datenobjekt und seine Präsentationen (Diagramm, Tabelle etc.) sollen sich bei einer Änderung automatisch aktualisieren.

Visitor (Besucher)

In einer Hierarchie mit vielen Klassen verteilt sich ein Algorithmus (in Form von Methoden) auf jede einzelne Klasse. Bei vielen Algorithmen wäre es schöner, wenn die Klassen­hierarchie zunächst unabhängig von den Algorithmen ist und ein Visitor, was einem Algorithmus-Objekt entspricht, die einzelnen Objekte traversiert und dann den Algorithmus entsprechend dem Objekt ausführt. Dadurch sind (objektspezifische) Algorithmen nicht mehr auf die Objekte verteilt, sondern beim Algorithmus-Objekt zentralisiert. Die Objekte müssen den Visitor akzeptieren und sich selbst an den Algorithmus übergeben.

Bsp: Syntaxbaum mit verschiedenen Knotenarten. Ein Visitor (Algorithmus) hat für jede Knotenart eine eigene Behandlung (je eine Methode).

Interpreter

Wird eine Sprache benutzt, die einer Grammatik folgt, so kann diese durch Objekte dargestellt werden (Terminal/Nichtterminal-Objekte), welche wiederum zum Bau eines Interpreters verhelfen, der Sätze der Sprache interpretieren kann.

Bsp: reguläre Ausdrücke

Iterator, Cursor

Man trennt die Listenstruktur von der Iteration derselben, indem man ein eigenes Iterator-Objekt entwirft, welches für die Traversierung zuständig ist. Dadurch können auf einer Liste verschiedene Iterationen stattfinden, Iterationen mit Filter sind möglich und dergleichen unabhängig von der inneren Struktur. Die Liste erzeugt einen Iterator mittels einer Fabrikmethode, so erzeugt die konkrete Liste ihren konkreten Iterator.

Bsp: Liste/Baum/Skipliste mit unterschiedlichen Traversierungen

Memento, Token

Ein Objekt (Urheber) soll seinen Zustand so speichern, dass ein eventuelles Undo möglich ist. Dies geschieht, indem der Klient ein Momento von dem Objekt anfordert, indem das Objekt seinen Zustand kodiert. Durch Rückgabe des Mementos an das Objekt kann dieses sich in den alten Zustand zurückversetzen. Andere Objekte können das Momento nicht interpretieren, die Kapselung bleibt bewahrt.

Bsp: Rückgängig, Breakpoints, Constraint-Löser.

Template Method (Schablonenmethode)

Eine Schablonenmethode stellt einen Algorithmus dar, von dem nur das Skelett existiert. Dieses wird aus primitiven (und vor allem abstrakten) Methoden zusammengesetzt. Damit ist der grobe Fahrplan des Algorithmus festgelegt, die abstrakten Methoden werden durch die Unterklassen implementiert. Anders gesagt: Wenn die Algorithmen der Unterklassen strukturell gleich sind und sich nur in spezifischen Implementierungen unterscheiden, so kann man diese Struktur mittels abstrakter Methoden auch schon in der Basisklasse festlegen.

Bsp: Dokument-Öffnen-Methode (ex?öffne!lade!) läuft immer gleich ab, lediglich der direkte Ladeteil hängt von der Dateiart - und damit von der Unterklasse - ab.

Strategy, Policy (Strategie)

Man entkoppelt Algorithmen vom Kontext-Objekt und erzeugt eigenständige Algorithmen-Objekte. Die Algorithmen-Objekte benutzen die gleiche Schnittstelle, wenn sie die gleiche Aufgabe bearbeiten. So kann dem Kontext-Objekt ein beliebiger Algorithmus (Auswahl durch den Klienten) zugeordnet werden zur Lösung der Aufgabe. Algorithmenverbesserung/-hinzunahme ist so ohne die Änderung des Kontext-Objektes möglich.

Bsp: Textbox benötigt (nun extern definierte) Zeilenumbruch-methode(n je nach Darstellung).

Mediator (Vermittler)

Wenn sich das Verhalten auf mehrere Objekte verteilt, so können Abhängigkeiten zwischen den Objekten entstehen, also erfordern Änderungen die Reaktionen anderer Objekte. Um nicht die Objekte/Klassen alle zu verknüpfen, wird ein Vermittler zwischengeschalten, der die Reaktion auf Veränderungen steuert. Alle Objekte sind nur mit dem Vermittler verknüpft, der Vermittler kennt alle beteiligten Objekte und steuert ihr abhängiges Verhalten.

Bsp: Widgets in einer Dialogbox reagieren abhängig voneinander (Listen laden sich neu, Buttons werden deaktiviert etc).

State (Zustand)

Reagiert ein Objekt abhängig von seinem Zustand völlig anders, so macht es Sinn, eine allgemeine ObjektZustandKlasse mit gleicher Schnittstelle wie das Objekt zu entwerfen. Für jeden konketen Zustand wird davon eine Unterklasse abgeleitet, die das jeweilige Verhalten implementiert. Das Objekt selbst aggregiert solch eine Klasse (wechselnd entsprechend ihrem Zustand) und leitet Anfragen direkt an ihr Zustandsobjekt weiter.

Bsp: Das TCPObjekt leitet Anfragen direkt an sein TCPZustandObjekt weiter (TCPEtabliert, TCPLauschend oder TCPGeschlossen).

Chain of Responsibility (Zuständigkeitskette)

Sendet ein Objekt eine Anfrage, wo der Empfänger noch nicht bekannt ist, bzw. die Anfrage an mehrere Objekte gerichtet ist, so kann man die potentiellen Empfänger entlang einer Kette testen, bis ein Objekt auf die Anfrage reagiert. Dabei kennt jedes Objekt einen Nachfolger bzgl. Zuständigkeit (Baumstrukturen etc. möglich).

Bsp: Kontexthilfe zu einem Button: Antwortet der Button nicht, so wird die Anfrage an die Dialogbox und anschließend an die Anwendung weitergereicht.

 

Kurzfassung

Erzeugungsmuster

Abstract Factory, ToolKit (Abstrakte Fabrik)

Objekte + deren Erzeugung vor Klient verbergen. Fabrik + Objekte dadurch austauschbar.

Builder (Erbauer)

Konstruktion und Präsentation trennen.

Factory Method, Virtual Constructor (Fabrikmethode)

Methode zum Erzeugen von Objekten von denen nur die abstrakte Basisklasse bekannt ist.

Prototype (Prototyp)

Ein Erzeuger kreiert Objekte mit der Clone-Fktn eines übergebenen Objektes (Prototypen).

Singleton

Garantiert, dass nur ein Objekt von diesem Typ erzeugt wird.

Strukturmuster

Adapter, Wrapper

Passt Schnittstellen vorhandener Objekte für Klienten an.

Bridge, Handle, Body (Brücke)

Trennt Abstraktion und Implementierung durch Abstraktionshierarchie und Implementierungshierarchie.

Decorator, Wrapper (Dekorierer)

Ummantelung von Objekten, wobei Funktionalität hinzugefügt wird.

Facade (Fassade)

Funktionalität und Vielfalt eines Subsystems wird auf eine Klasse konzentriert + beschränkt.

Flyweight (Fliegengewicht)

Kontextabhängige Information wird aus einem Objekt entfernt und extern verwaltet, um so die Anzahl benötigter Klassen zu minimieren.

Composite (Kompositum)

Gruppierung von Objekten, wobei die Gruppe selbst wieder Objekt gleicher Art ist.

Proxy, Surrogat

Steuerung schwerfälliger bzw. zugriffsbeschränkter Objekte.

Verhaltensmuster

Command, Action, Transaction (Befehl)

Befehle werden als Objekte gekapselt, die dann herumgereicht werden können.

Observer, Publish-Subscribe-Methode (Beobachter)

Die Änderung eines Objektes zieht die Änderung anderer nach sich, gesteuert vom Observer.

Visitor (Besucher)

Algorithmen werden aus den Klassen gelöst und in Algorithmenklassen konzentriert.

Interpreter

Überführung einer Grammatik in Objekte zur Konstruktion eines Interpreters.

Iterator, Cursor

Trennung von Listen-Datenstruktur und Element-Traversion/Iteration mittels Iteratorobjekts.

Memento, Token

Innerer-Zustand-Speicherung für Undo-Operationen ohne Aufhebung der Kapselung.

Template Method (Schablonenmethode)

Aus Primitivmethoden zusammengesetzte Skelett-Algorithmen, wobei die Primitiven durch Nachfolgeklassen implementiert werden.

Strategy, Policy (Strategie)

Trennung von Algorithmen und Objekten durch austauschbare Algorithmen-Objekte.

Mediator (Vermittler)

Objektabhängigkeiten werden nicht durch die Objekte sondern Vermittler festgelegt.

State (Zustand)

Objekt delegiert Verhalten an aggregiertes austauschbares Zustandsobjekt.

Chain of Responsibility (Zuständigkeitskette)

Anfrage wird entlang einer Kette an potentielle Empfänger weitergereicht.

Literatur:

Entwurfsmuster von Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (Gang of Four); Übersetzung Dirk Riehle; Addison-Wesley 1996; ISBN: 3-89319-950-0

Wir distanzieren uns von externen verlinkten Inhalten. Impressum: Sven Hanke — contact german german Arbeiten Graphen Genom-DB Text CBR GOF Kunst Theorie Baby Lach Funky3D HelpCreator xorDX8 xorAnalyzer Links