Design Patterns
Aus Wiklet
Der Begriff Pattern kommt aus der Architektur. Was darunter zu verstehen ist, wird kurz zusammengefaßt. Darauf aufbauend werden Design Patterns dargestellt. Schwerpunkte sind ihr Aufbau, die Beziehung zwischen verschiedenen Design Patterns und ihr Nutzen.
Inhaltsverzeichnis |
[Bearbeiten] Der Begriff Pattern
Laut Christopher Alexander, Professor für Architektur an der Universität Berkley, ist jedes Pattern eine dreiteilige Regel, welche die Beziehung zwischen einem gewissen Kontext, einem Problem und seiner Lösung ausdrückt. Jedes Pattern beschreibt ein Problem, das immer wieder vorkommt und dadurch wieder und wieder angewendet werden kann. Dabei bezeichnet man mit dem Ausdruck Pattern sowohl das Ergebnis, das durch die Anwendung der Regel entsteht, als auch die Regel selbst.
Beispiel für ein Architektur-Pattern ist das Ring Roads-Pattern [Alexander et al.1977]. Das Problem und der Kontext werden wie folgt dargestellt:
It is not possible to avoid the need for high speed roads in modern society; but it is essential to place them and build them in such a way that they do not destroy communities or countryside.
Die Lösung wird durch die Skizze dargestellt und folgendermaßen beschrieben:
Place high speed roads (freeways or other major arteries) so that:
- At least one high speed road lies tangent to each local transport area.
- Each local transport area has at least one side not bound by a high speed road, but directly open to the countryside.
- The road is always sunken, or shielded along its length by berms, or earth, or industrial buildings, to protect the nearby neighborhoods from noise.
Bild:Ringroad pattern.gif Natürlich bezog sich Alexander auf die Baukunst, doch ist der Pattern-Ansatz fast unverändert für die Softwareentwicklung anwendbar.
[Bearbeiten] Das Design Pattern
Design Patterns sind Beschreibungen von Lösungen für Software-Design Probleme, die mehreren Kriterien genügen müssen. Sie müssen mindestens den Kontext, das Problem und die Lösung darstellen. Außerdem müssen die Beschreibungen in einer festgelegten Form erfolgen, damit man die Patterns miteinander vergleichen und in ein Schema einordnen kann. Für diesen Zweck haben in den letzten Jahren viele Autoren Formulare entwickelt, die auf die Anforderungen von Design Patterns für die Softwareentwicklung abgestimmt sind. Die Struktur des bekanntesten Formulars wurde von Erich Gamma und seinen Kollegen [Gamma et al.1993] entwickelt. Da dieses aber die Objekt-Orientierung überbetont, wird hier das Formular aus [Buschmann and Meunier1995] verwendet. Es hat folgendes Aussehen:
- Name (Name). Der Name und eine kurze Beschreibung des Patterns. Der Name soll das Problem und seine Lösung bezeichnen. Er muß sehr sorgfältig gewählt werden, da er direkt in das Design-Vokabular aufgenommen wird. Das heißt, der Name wird später stellvertretend für alle wichtigen Aspekte des gesamten Pattern verwendet. Dies erleichtert die Kommunikation zwischen Designern. Schlägt einer die Verwendung eines bestimmten Patterns vor, weiß der andere sofort, was gemeint ist. Die Beschreibung soll am besten in einem Satz darstellen, welche Probleme mit diesem Pattern angesprochen werden.
- Auch bekannt als (Also Known As). Ein alternativer Name, unter dem dieses Design Pattern bekannt ist.
- Beispiel (Example). Es wird ein Beispiel beschrieben, das die Existenz des Design Problems zeigt. Das Beispiel hilft, die abstrakte Beschreibung des Patterns leichter zu verstehen.
- Kontext (Context). Beschreibung der Situation, in der das Pattern angewandt werden kann.
- Problem (Problem). Das Problem, das vom Pattern behandelt wird. Es wird zuerst der Kern des Problems allgemein beschrieben. Danach werden Erfordernisse, Einschränkungen und wünschenswerte Eigenschaften des Ergebnisses aufgezählt und beschrieben.
- Lösung (Solution). Das grundsätzliche Prinzip, das der Lösung zugrunde liegt.
- Struktur (Structure). Hier werden die Konfiguration der beteiligten Komponenten und ihre Beziehungen untereinander beschrieben. Es wird in der Regel eine grafische Repräsentation zur Beschreibung verwendet. Als Notation für objekt-orientiertes Design bietet sich die Object Modeling Technique [Rumbaugh et al.1991] an.
- Laufzeit Verhalten (Dynamics). Beschreibt, wie die Komponenten zusammenarbeiten. Es handelt sich dabei um die dynamischen Aspekte des Systems, die das Laufzeit-Verhalten bestimmen.
- Implementation (Implementation). Hinweise auf Probleme und Besonderheiten bei der Implementation des Patterns. Es handelt sich um Vorschläge und keine Regeln, da die Implementation an die speziellen Bedürfnisse jedes Einzelfalls angepaßt werden muß. Es können auch Programmteile als Beispiele zur Illustration einer möglichen Implementation angegeben werden.
- Gelöste Beispiele (Examples Resolved). Eine Beschreibung der wichtigen Aspekte für die Lösung des Beispiels, die bis jetzt noch nicht erklärt wurden.
- Varianten (Variants). Eine kurze Beschreibung von Varianten oder Spezialisierungen des Patterns.
- Bekannte Anwendungen (Known Uses). Beispiele von existierenden Systemen, in denen das Pattern verwendet wird.
- Konsequenzen (Consequences). Beschreibt die Ergebnisse und Einschränkungen, die sich aus der Anwendung des Patterns ergeben. Es ist unwahrscheinlich, daß ein Pattern alle Probleme vollständig lösen kann. Darum ist es wichtig hier auf vom Pattern ungelöste Probleme einzugehen. Die Beschreibung der Konsequenzen ist das Kriterium für die Auswahl bei alternativen Patterns.
- Siehe auch (See Also). Patterns, die ähnliche Probleme lösen oder die helfen das eben beschriebene Pattern zu verfeinern.
Andere Autoren fassen Punkte aus diesem Formular zusammen oder verwenden zusätzliche, um bestimmte Aspekte zu betonen. Im großen und ganzen sind sie diesem Formular sehr ähnlich.
[Bearbeiten] Kategorisierung von Design Patterns
Da man nicht alle Patterns kennen kann, benötigt man eine Übersicht über diese. Es muß eine Ordnung in die Patterns gebracht werden, die es erlaubt die geeigneten Patterns für ein bestimmtes Problem zu finden. Mehrere Autoren haben Patterns nach gewissen Kriterien geordnet.
Erich Gamma und seine Mitautoren [Gamma et al.1993,Gamma et al.1995] teilen Design Patterns nach zwei Klassifikationskriterien ein. Dies sind der Umfang der Patterns und ihr Zweck. Nach dem Umfang werden Patterns für Klassen und für Objekte unterschieden, da ausschließlich objekt-orientierte Patterns beschrieben werden. Nach dem Zweck werden Patterns in die Kategorien Creational, Structural und Behavioral eingeteilt. Creational Patterns beschäftigen sich mit der Erzeugung von Objekten. Structural Patterns beschreiben die statische Zusammensetzung von Objekten und Klassen. Behavioral Patterns charakterisieren das dynamische Verhalten von Objekten und Klassen. Erich Gamma hat über zwanzig Patterns beschrieben und in sein Schema eingefügt. Beispiele sind die Patterns Abstract Factory, Adapter und Strategy.
Frank Buschman und seine Kollegen [Buschmann and Meunier1995,Buschmann et al.1996] teilen Patterns nach ihrem Abstraktionsgrad ein. Er beginnt mit der höchsten Abstraktionsstufe und nennt diese Architectural Patterns. Diese erklären die fundamentale strukturelle Organisation von Softwaresystemen. Sie geben die nötigen Subsysteme an und spezifizieren ihre Funktionen und Beziehungen zueinander. In der mittleren Abstraktionsebene werden Design Patterns verwendet. Diese zeigen wie Subsysteme oder Komponenten verfeinert werden. Sie lösen immer wiederkehrende Design Probleme. Die geringste Abstraktion weisen Idioms auf. Sie sind speziell für Probleme, die im Zusammenhang mit einer bestimmten Programmiersprache auftreten, bestimmt. Wichtige Idioms für eine Sprache können für eine andere nutzlos sein. Als zweites Klassifikationskriterium wird der zu lösende Problembereich verwendet. Einige solcher Problembereiche sind zum Beispiel Communication, Access Control und Distributed Systems. Die Liste der Problembereiche ist erweiterbar und kann bei Bedarf ergänzt werden. In dieses Schema wurden auch rund zwanzig Patterns eingeordnet. Die Patterns decken sich großteils mit den schon von Gamma präsentierten.
Walter Zimmer [Zimmer1995] geht von den Patterns in [Gamma et al.1995] aus. Da Patterns nur selten alleine existieren, versucht Zimmer die Beziehungen zwischen den einzelnen Patterns aufzuzeigen. Zur Beschreibung der Beziehungen verwendet er drei Kategorien. Diese sind X verwendet Y in seiner Lösung, eine Variante von X verwendet Y in seiner Lösung und X ist ähnlich wie Y. X und Y bezeichnen zwei betrachtete Patterns. Die Beziehungen werden als Graphen zwischen den Patterns dargestellt. Danach führt Zimmer drei Schichten ein, denen er die Patterns zuordnet. Die unterste Schicht nennt er Basic Design Patterns and Techniques. Sie beinhaltet Patterns, die für sehr generelle Probleme angewandt werden. Sie werden regelmäßig durch Patterns der höheren Schichten verwendet. Design Patterns for Typical Software Problems heißt die mittlere Schicht. Patterns dieser Schicht werden für speziellere Probleme verwendet. Die oberste Schicht nennt Zimmer Design Patterns Specific to an Application Domain. Sie beinhaltet Patterns, die für einen oder mehrere Bereiche des Software Designs verwendet werden können. Durch die hierarchische Einordnung der Patterns und der grafischen Darstellung der Beziehungen zwischen ihnen wird die Orientierung in einem System von Patterns sehr erleichtert. Die oft schwer erkennbaren Zusammenhänge und Abhängigkeiten werden explizit dargestellt.
Von einer Pattern Language, wie sie Alexander [Alexander et al.1977] für die Architektur vorstellt, ist man bei Design Patterns für Software Probleme noch weit entfernt. Eine solche Sprache müßte Lösungen für alle Design Probleme eines bestimmten Bereiches bieten, um komplett zu sein. Dies wurde bisher nur für sehr beschränkte Teilbereiche erreicht. Ein Beispiel für den Bereich Informationsintegrität ist die Pattern Language CHECKS [Cunningham1995]. Die Frage, die sich in diesem Zusammenhang stellt ist, ob eine vollständige Pattern Language für Softwaredesign überhaupt sinnvoll ist. Möglicherweise ist es ausreichend, die bisher vorgestellten Pattern-Systeme weiter auszubauen und zu verfeinern.
[Bearbeiten] Klassifikation
Die Gang of Four klassifziert Muster nach den beiden Kriterien des Zwecks (purpose) und des Bereichs, auf dem sie wirken (scope).
Nach dem Zweck des jeweiligen Musters unterscheidet sie drei Klassen: Die erste Gruppe der Erzeugungsmuster bezieht sich auf die Erzeugung von Objekten. So kann man etwa die Anzahl von erzeugten Objekten einer Klasse kontrollieren wollen, oder man will den konkreten Typ der erzeugten Objekte - abhängig von den jeweiligen Bedingungen - anpassen. Die zweite Gruppe umfasst Strukturmuster, welche eine Vereinfachung der Struktur zwischen Klassen ermöglichen sollen. Komplexe Beziehungsgeflechte können beispielsweise über vermittelnde Klassen oder Schnittstellen logisch vereinfacht werden. Die dritte Gruppe der Verhaltensmuster betrifft das Verhalten der Klassen. Hierbei handelt es sich um die größte Gruppe von Mustern. Sie beziehen sich auf die Zusammenarbeit und den Nachrichtenaustausch von Klassen.
Nach ihrem Anwendungsbereich lassen sich Muster in Klassen- und Objektmuster einteilen. Klassenmuster beschreiben Beziehungen zwischen Klassen und bauen vorrangig Vererbungsstrukturen auf. Die Strukturen sind damit zur Übersetzungszeit festgelegt. Hingegen nutzen Objektmuster vorrangig Assoziationen und Aggregationen zur Beschreibung von Beziehungen zwischen Objekten. Die durch sie beschriebenen Strukturen zwischen Objekten sind zur Laufzeit dynamisch änderbar.
[Bearbeiten] Erzeugungsmuster (Creational Patterns)
Erzeugungsmuster abstrahieren Objekterzeugungsprozesse. Klassenmuster nutzen dabei Vererbung, um die Klasse des zu erzeugenden Objekts zu variieren. Objektmuster delegieren die Objekterzeugung an andere Objekte.
- Klassenmuster
- Objektmuster
[Bearbeiten] Strukturmuster (Structural Patterns)
Strukturmuster fassen Klassen und Objekte zu größeren Strukturen zusammen. Klassenmuster fassen dabei Schnittstellen und Implementationen zusammen, während Objektmuster Objekte in eine Struktur einordnen. Durch Klassenmuster beschriebene Strukturen sind zur Übersetzungszeit festgelegt. Die durch Objektmuster beschriebenen Strukturen sind zur Laufzeit änderbar.
- Klassenmuster
- Adapter (Wrapper)
- Objektmuster
[Bearbeiten] Verhaltensmuster (Behavioral Patterns)
Verhaltensmuster beschreiben die Interaktion zwischen Objekten und komplexe Kontrollflüsse. Klassenmuster teilen die Kontrolle auf verschiedene Klassen auf, Objektmuster nutzen Aggregationen.
- Klassenmuster
- Objektmuster
[Bearbeiten] Andere Entwurfsmuster
Die Arbeiten der Gang of Four haben viele Autoren zu weiteren Veröffentlichungen über Entwurfsmuster angeregt. Ein weiteres bekanntes Muster ist:
- Actor-Role Pattern
Der Gedanke der Muster hat inzwischen auch in anderen Bereichen der Informatik zu weiteren Veröffentlichungen geführt:
- Martin Fowler: Analysis Patterns
- Adam Bien: J2EE Patterns
- Frank Buschmann: Pattern-Oriented Software Architecture, Vol.1 : A System of Patterns
[Bearbeiten] Nutzen von Design Patterns
Patterns werden von erfahrenen Software Designern schon sehr lange verwendet. Das Problem bis vor kurzem war, daß jeder Designer "seine" Patterns selbst entwickeln mußte, da keine geeignete Möglichkeit bekannt war, das Wissen in geordneter Form weiterzugeben. Patterns bieten diese Möglichkeit. Ihre Verwendung zur Beschreibung von Problem-Lösungs Beziehungen bringen laut [Gamma et al.1995] folgende vier große Vorteile:
Ein gemeinsames Design Vokabular. Patterns bieten durch ihren Namen eine einfache Möglichkeit zu Kommunikation und Dokumentation. Kennen mehrere Designer bestimmte Patterns, reicht ihr Name aus, um über Designalternativen zu sprechen. Die Namen der Patterns bilden ihr gemeinsames Vokabular.
Eine Dokumentations- und Lernhilfe. Bei großen objekt-orientierten Systemen werden oft unbewußt Design Patterns verwendet. Beschreibt man so ein System mit Design Patterns, die im System gefunden werden, kann seine Funktion viel schneller und leichter verstanden werden. Da Design Patterns für allgemeine Probleme, die immer wieder vorkommen, Lösungen bieten, liegt es nahe sie für Lehrzwecke zu verwenden. In [Goldfedder and Rising1996] werden Erfahrungen über den Unterricht mit Patterns beschrieben.
Eine Erweiterung zu existierenden Methoden. Existierende Design Methoden beschreiben Probleme, die während des Designs auftreten und bieten passende Lösungen an. Sie vernachlässigen jedoch den Bereich der Erfahrung. Design Patterns können folgende Vorteile in die Design Phase einbringen:
- Design Patterns beinhalten Erfahrung von Design Experten.
- Design Patterns beschreiben, warum eine bestimmte Design Alternative (ein Pattern) verwendet wird, und die sich daraus ergebenden Konsequenzen. Daher können Design Entscheidungen später leichter nachvollzogen werden.
- Design Patterns bringen flexibles und wiederverwendbares Design aus der Design Phase in die Analyse Phase. Dadurch wird der Übergang vom Analysemodell zum Designmodell einfacher, und das Analysemodell muß später nicht nachträglich verändert werden, um flexibles Design zu ermöglichen.
Ein Ziel für Refactoring. Software, die lange verwendet werden soll, steht irgendwann vor dem Problem, daß sich mit der Zeit die Anforderungen, die sie zu erfüllen hat, ändern. Oft werden zusätzliche Anforderungen durch Erweiterungen der Software befriedigt. Dies führt aber zu einem inflexiblen System, das für spätere Anpassungen ungeeignet ist. Um die Software weiter zu entwickeln, muß sie umorganisiert werden. Dieser Prozeß heißt Refactoring.
Design Patterns beschreiben Strukturen, die das Resultat von Refactoring sind. Dadurch zeigen sie die Richtung, in die ein inflexibles Software System umorganisiert werden soll, um auch zukünftigen Anforderungen gewachsen zu sein. Geht man noch einen Schritt weiter, und verwendet Patterns im Design von neuer Software, wird der Bedarf für Refactoring zu einem späteren Zeitpunkt verringert oder sogar ganz vermieden.
Die Aufzählung der Vorteile wurde von einigen Autoren verfeinert, aber der Inhalt blieb weitgehend gleich. Marschall Cline [Cline1996] beschreibt neben den Vorteilen von Design Patterns auch folgende Problembereiche:
Überbewertung des Ansatzes. Der Anwendungsbereich, in dem Design Patterns effizient angewandt werden können, ist schwer zu erkennen. Durch die Verwendung von Design Patterns entstehen zusätzliche Kosten, die auch gerechtfertigt sein müssen. Design Patterns ersparen nur dann Kosten, wenn die Software später verändert oder angepaßt werden muß. Ist dies nicht der Fall, bringt die Verwendung von Patterns nicht alle Vorteile.
Einige Design Patterns sind unnötig schwer zu erlernen. Da viele Designer Patterns entwickeln oder Patterns von anderen verändern, geht oft die Klarheit des Designs verloren.
Unbrauchbare Kategorisierungen von Design Patterns. Design Patterns werden, wie schon beschrieben, nach verschiedenen Kriterien eingeteilt. Diese Kriterien sind aber großteils für den durchschnittlichen Designer nicht verständlich, da sie zu stark auf das gemeinsame Design-Vokabular der Patterns abgestimmt sind.
Die beschriebenen Probleme sind großteils darauf zurückzuführen, daß der Patterns Ansatz noch nicht ausgereift ist. Es ist anzunehmen, daß sie im weiteren Entwicklungsprozeß des Pattern-Ansatzes abnehmen werden.

