Entwurfsmuster
In der Softwaretechnik ist ein Software-Entwurfsmuster eine allgemeine, wiederverwendbare Lösung für ein häufig auftretendes Problem in einem bestimmten Kontext des Softwareentwurfs. Es handelt sich nicht um einen fertigen Entwurf, der direkt in Quell- oder Maschinencode umgewandelt werden kann. Vielmehr handelt es sich um eine Beschreibung oder Vorlage für die Lösung eines Problems, die in vielen verschiedenen Situationen verwendet werden kann. Entwurfsmuster sind formalisierte Best Practices, die der Programmierer zur Lösung gängiger Probleme beim Entwurf einer Anwendung oder eines Systems verwenden kann. ⓘ
Objektorientierte Entwurfsmuster zeigen in der Regel Beziehungen und Interaktionen zwischen Klassen oder Objekten auf, ohne die endgültigen Anwendungsklassen oder Objekte zu spezifizieren, die daran beteiligt sind. Muster, die einen veränderlichen Zustand implizieren, sind für funktionale Programmiersprachen möglicherweise ungeeignet. Einige Muster können sich in Sprachen erübrigen, die über eine eingebaute Unterstützung für die Lösung des Problems verfügen, das sie zu lösen versuchen, und objektorientierte Muster sind nicht unbedingt für nicht objektorientierte Sprachen geeignet. ⓘ
Entwurfsmuster können als ein strukturierter Ansatz für die Computerprogrammierung betrachtet werden, der zwischen den Ebenen eines Programmierparadigmas und eines konkreten Algorithmus liegt. ⓘ
Entwurfsmuster (englisch design patterns) sind bewährte Lösungsschablonen für wiederkehrende Entwurfsprobleme sowohl in der Architektur als auch in der Softwarearchitektur und -entwicklung. Sie stellen damit eine wiederverwendbare Vorlage zur Problemlösung dar, die in einem bestimmten Zusammenhang einsetzbar ist. In den letzten Jahren hat der Ansatz der Entwurfsmuster auch zunehmendes Interesse im Bereich der Mensch-Computer-Interaktion gefunden. Ursprünglich wurde der Begriff in der Architektur von Christopher Alexander verwendet. ⓘ
Geschichte
Patterns wurden bereits 1977 von Christopher Alexander als architektonisches Konzept entwickelt (vgl. "The Pattern of Streets", JOURNAL OF THE AIP, September 1977, Vol. 32, No. 3, pp. 273-278). 1987 begannen Kent Beck und Ward Cunningham mit der Idee zu experimentieren, Muster auf die Programmierung anzuwenden - insbesondere auf Mustersprachen - und präsentierten ihre Ergebnisse auf der OOPSLA-Konferenz in diesem Jahr. In den folgenden Jahren haben Beck, Cunningham und andere diese Arbeit weiterverfolgt. ⓘ
Design Patterns wurden in der Informatik populär, nachdem das Buch Design Patterns: Elements of Reusable Object-Oriented Software 1994 von der so genannten "Gang of Four" (Gamma et al.) veröffentlicht wurde, die häufig als "GoF" abgekürzt wird. Im selben Jahr fand die erste Pattern Languages of Programming Conference statt, und ein Jahr später wurde das Portland Pattern Repository zur Dokumentation von Entwurfsmustern eingerichtet. Der Umfang des Begriffs ist nach wie vor umstritten. Zu den bemerkenswerten Büchern im Bereich der Entwurfsmuster gehören:
- Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. ISBN 978-0-201-63361-0.
- Brinch Hansen, Per (1995). Studien zur Computerwissenschaft: Parallele Programmierparadigmen. Prentice Hall. ISBN 978-0-13-439324-7.
- Buschmann, Frank; Meunier, Regine; Rohnert, Hans; Sommerlad, Peter (1996). Musterorientierte Softwarearchitektur, Band 1: Ein System von Mustern. John Wiley & Sons. ISBN 978-0-471-95869-7.
- Beck, Kent (1997). Smalltalk Best Practice Patterns. Prentice Hall. ISBN 978-0134769042.
- Schmidt, Douglas C.; Stal, Michael; Rohnert, Hans; Buschmann, Frank (2000). Musterorientierte Softwarearchitektur, Band 2: Muster für gleichzeitige und vernetzte Objekte. John Wiley & Sons. ISBN 978-0-471-60695-6.
- Fowler, Martin (2002). Muster für die Anwendungsarchitektur von Unternehmen. Addison-Wesley. ISBN 978-0-321-12742-6.
- Hohpe, Gregor; Woolf, Bobby (2003). Muster für die Unternehmensintegration: Designing, Building, and Deploying Messaging Solutions. Addison-Wesley. ISBN 978-0-321-20068-6.
- Freeman, Eric T.; Robson, Elisabeth; Bates, Bert; Sierra, Kathy (2004). Head First Entwurfsmuster. O'Reilly Media. ISBN 978-0-596-00712-6.
Obwohl Entwurfsmuster schon seit langem in der Praxis angewandt werden, blieb die Formalisierung des Konzepts der Entwurfsmuster mehrere Jahre lang aus. ⓘ
Ein Ansatz für Entwurfsmuster wurde vom Architekten Christopher Alexander 1964 in Notes on the synthesis of form dargestellt. Zwischen 1977 und 1979 stellte er dann, in einer auf den römischen Architekten Marcus Vitruvius Pollio, genannt Vitruv, zurückgehenden Tradition, eine Sammlung von Entwurfsmustern zusammen. Die Hauptaufgabe dieser Muster war es, die Bewohner der zu bauenden Strukturen in den Entwurfsprozess mit einzubinden. In der Architektur hat sich diese Idee jedoch bei weitem nicht so verbreitet wie später in der Softwareentwicklung. ⓘ
Kent Beck und Ward Cunningham griffen 1987 die Ideen Alexanders aus der Architektur auf und entwickelten Entwurfsmuster für die Erstellung von grafischen Benutzeroberflächen in Smalltalk. Ein Jahr später begann Erich Gamma mit seiner Promotion an der Universität Zürich über die generelle Übertragung dieser Methode auf die Softwareentwicklung. Parallel dazu arbeitete James Coplien in den Jahren 1989 bis 1991 an musterähnlichen Idiomen für C++ und veröffentlichte 1991 sein Buch Advanced C++ Idioms. ⓘ
Erich Gamma beendete im selben Jahr seine Promotion und ging im Anschluss in die Vereinigten Staaten. Dort brachte er 1994 zusammen mit Richard Helm, Ralph Johnson und John Vlissides das Buch Design Patterns – Elements of Reusable Object-Oriented Software heraus, in dem 23 Entwurfsmuster beschrieben sind. Die vier Autoren sind unter Entwicklern weltweit auch unter ihrem Spitznamen Gang of Four (Viererbande), kurz GoF, bekannt und verhalfen mit ihrem Buch den Entwurfsmustern zu einem Durchbruch. Gelegentlich wird GoF auch als Verweis auf das besagte Buch verwendet. Anders als Alexander, der seine Muster vor allem für Laien geschrieben hatte, richten sich die GoF-Muster an Softwareentwickler und nicht an Benutzer. ⓘ
Praxis
Entwurfsmuster können den Entwicklungsprozess beschleunigen, indem sie getestete, bewährte Entwicklungsparadigmen bereitstellen. Ein effektiver Softwareentwurf erfordert die Berücksichtigung von Problemen, die möglicherweise erst später bei der Implementierung sichtbar werden. Frisch geschriebener Code kann oft versteckte, subtile Probleme aufweisen, die erst nach einiger Zeit entdeckt werden und die später zu großen Problemen führen können. Die Wiederverwendung von Entwurfsmustern trägt dazu bei, solche subtilen Probleme zu vermeiden, und sie verbessert auch die Lesbarkeit des Codes für Programmierer und Architekten, die mit den Mustern vertraut sind. ⓘ
Um Flexibilität zu erreichen, führen Entwurfsmuster in der Regel zusätzliche Ebenen der Indirektion ein, die in einigen Fällen die resultierenden Entwürfe verkomplizieren und die Anwendungsleistung beeinträchtigen können. ⓘ
Per Definition muss ein Muster in jeder Anwendung, die es verwendet, neu programmiert werden. Da einige Autoren darin einen Rückschritt gegenüber der Wiederverwendung von Software sehen, wie sie durch Komponenten ermöglicht wird, haben Forscher daran gearbeitet, Muster in Komponenten umzuwandeln. Meyer und Arnout waren in der Lage, zwei Drittel der von ihnen untersuchten Muster ganz oder teilweise in Komponenten umzuwandeln. ⓘ
Softwareentwurfstechniken lassen sich nur schwer auf ein breiteres Spektrum von Problemen anwenden. Entwurfsmuster bieten allgemeine Lösungen, die in einem Format dokumentiert sind, das keine spezifischen, an ein bestimmtes Problem gebundenen Angaben erfordert. ⓘ
Aufbau
Entwurfsmuster setzen sich aus mehreren Abschnitten zusammen (siehe § Dokumentation unten). Von besonderem Interesse sind die Abschnitte "Struktur", "Teilnehmer" und "Zusammenarbeit". Diese Abschnitte beschreiben ein Entwurfsmotiv: eine prototypische Mikroarchitektur, die Entwickler kopieren und an ihre eigenen Entwürfe anpassen, um das durch das Entwurfsmuster beschriebene wiederkehrende Problem zu lösen. Eine Mikroarchitektur ist ein Satz von Programmbestandteilen (z.B. Klassen, Methoden...) und deren Beziehungen. Die Entwickler verwenden das Entwurfsmuster, indem sie in ihren Entwürfen diese prototypische Mikroarchitektur einführen, was bedeutet, dass die Mikroarchitekturen in ihren Entwürfen eine ähnliche Struktur und Organisation wie das gewählte Entwurfsmotiv aufweisen werden. ⓘ
Bereichsspezifische Muster
Es wurden auch Anstrengungen unternommen, Entwurfsmuster in bestimmten Bereichen zu kodifizieren, einschließlich der Verwendung bestehender Entwurfsmuster sowie bereichsspezifischer Entwurfsmuster. Beispiele hierfür sind Entwurfsmuster für Benutzeroberflächen, Informationsvisualisierung, sicheres Design, "sichere Benutzerfreundlichkeit", Web-Design und Geschäftsmodell-Design. ⓘ
Die jährlichen Proceedings der Pattern Languages of Programming Conference enthalten viele Beispiele für bereichsspezifische Muster. ⓘ
Klassifizierung und Liste
Entwurfsmuster wurden ursprünglich in 3 Unterkategorien eingeteilt, je nachdem, welche Art von Problem sie lösen. Schöpfungsmuster bieten die Möglichkeit, Objekte auf der Grundlage eines erforderlichen Kriteriums und auf kontrollierte Weise zu erstellen. Bei strukturellen Mustern geht es darum, verschiedene Klassen und Objekte zu organisieren, um größere Strukturen zu bilden und neue Funktionen bereitzustellen. Bei Verhaltensmustern schließlich geht es darum, gemeinsame Kommunikationsmuster zwischen Objekten zu erkennen und diese Muster zu verwirklichen. ⓘ
Schöpferische Muster
Name | Beschreibung | In Entwurfsmustern | In Code vervollständigen | Andere ⓘ |
---|---|---|---|---|
Abstrakte Fabrik | Bietet eine Schnittstelle zur Erstellung von Familien verwandter oder abhängiger Objekte, ohne deren konkrete Klassen anzugeben. | Ja | Ja | — |
Ersteller | Trennung der Konstruktion eines komplexen Objekts von seiner Darstellung, so dass derselbe Konstruktionsprozess verschiedene Darstellungen erzeugen kann. | Ja | Nein | — |
Dependency Injection | Eine Klasse nimmt die von ihr benötigten Objekte von einem Injektor entgegen, anstatt die Objekte direkt zu erstellen. | Nein | Nein | — |
Factory-Methode | Definieren Sie eine Schnittstelle für die Erstellung eines einzelnen Objekts, aber lassen Sie Unterklassen entscheiden, welche Klasse instanziiert werden soll. Die Factory-Methode ermöglicht es einer Klasse, die Instanziierung auf Unterklassen zu verschieben. | Ja | Ja | — |
Faule Initialisierung | Taktik, die Erstellung eines Objekts, die Berechnung eines Werts oder einen anderen kostspieligen Prozess so lange hinauszuzögern, bis er das erste Mal benötigt wird. Dieses Muster erscheint im GoF-Katalog als "virtueller Proxy", eine Implementierungsstrategie für das Proxy-Muster. | Nein | Nein | PoEAA |
Mehrere Instanzen | Stellen Sie sicher, dass eine Klasse nur benannte Instanzen hat, und bieten Sie einen globalen Zugriffspunkt für diese Instanzen an. | Nein | Nein | — |
Objekt-Pool | Vermeiden Sie die teure Beschaffung und Freigabe von Ressourcen, indem Sie Objekte, die nicht mehr verwendet werden, wiederverwenden. Kann als Verallgemeinerung der Muster für Verbindungspools und Threadpools betrachtet werden. | Nein | Nein | — |
Prototyp | Spezifizieren Sie die Arten von Objekten, die mit Hilfe einer prototypischen Instanz erstellt werden sollen, und erstellen Sie neue Objekte auf der Grundlage des "Skeletts" eines bestehenden Objekts, um so die Leistung zu steigern und den Speicherbedarf auf ein Minimum zu beschränken. | Ja | Nein | — |
Ressourcenerwerb ist Initialisierung (RAII) | Sicherstellen, dass die Ressourcen ordnungsgemäß freigegeben werden, indem sie an die Lebensdauer geeigneter Objekte gebunden werden. | Nein | Nein | — |
Singleton | Sicherstellen, dass eine Klasse nur eine Instanz hat, und einen globalen Zugangspunkt zu ihr bereitstellen. | Ja | Ja | — |
Strukturelle Muster
Name | Beschreibung | In Entwurfsmustern | In Code vervollständigen | Andere ⓘ |
---|---|---|---|---|
Adapter, Wrapper oder Übersetzer | Konvertieren die Schnittstelle einer Klasse in eine andere Schnittstelle, die Kunden erwarten. Ein Adapter ermöglicht die Zusammenarbeit von Klassen, die sonst aufgrund inkompatibler Schnittstellen nicht zusammenarbeiten könnten. Das Äquivalent zum Enterprise Integration Pattern ist der Translator. | Ja | Ja | — |
Brücke | Entkopplung einer Abstraktion von ihrer Implementierung, so dass die beiden unabhängig voneinander variieren können. | Ja | Ja | — |
Zusammengesetzt | Komposition von Objekten in Baumstrukturen zur Darstellung von Teil-Ganzes-Hierarchien. Mit Composite können Clients einzelne Objekte und Kompositionen von Objekten einheitlich behandeln. | Ja | Ja | — |
Dekorateur | Fügen Sie einem Objekt dynamisch zusätzliche Verantwortlichkeiten hinzu, wobei die gleiche Schnittstelle beibehalten wird. Decorators bieten eine flexible Alternative zum Subclassing für die Erweiterung der Funktionalität. | Ja | Ja | — |
Erweiterungsobjekt | Hinzufügen von Funktionalität zu einer Hierarchie, ohne die Hierarchie zu verändern. | Nein | Nein | Agile Softwareentwicklung, Prinzipien, Muster und Praktiken |
Fassade | Bereitstellung einer einheitlichen Schnittstelle für eine Reihe von Schnittstellen in einem Teilsystem. Facade definiert eine übergeordnete Schnittstelle, die die Nutzung des Subsystems erleichtert. | Ja | Ja | — |
Fliegengewicht | Gemeinsame Nutzung, um eine große Anzahl ähnlicher Objekte effizient zu unterstützen. | Ja | Nein | — |
Front-Controller | Das Muster bezieht sich auf den Entwurf von Webanwendungen. Es bietet einen zentralen Einstiegspunkt für die Bearbeitung von Anfragen. | Nein | Nein |
J2EE-Muster PoEAA |
Markierung | Leere Schnittstelle, um Metadaten mit einer Klasse zu verknüpfen. | Nein | Nein | Wirksames Java |
Modul | Gruppierung mehrerer zusammengehöriger Elemente, wie Klassen, Singletons, Methoden, global verwendet, in einer einzigen konzeptionellen Einheit. | Nein | Nein | — |
Proxy | Ein Surrogat oder Platzhalter für ein anderes Objekt bereitstellen, um den Zugriff darauf zu kontrollieren. | Ja | Nein | — |
Zwilling | Twin ermöglicht die Modellierung von Mehrfachvererbung in Programmiersprachen, die diese Funktion nicht unterstützen. | Nein | Nein | — |
Verhaltensmuster
Name | Beschreibung | In Entwurfsmustern | In Code vervollständigen | Andere ⓘ |
---|---|---|---|---|
Schwarzes Brett | Muster der künstlichen Intelligenz zur Kombination unterschiedlicher Datenquellen (siehe Blackboard-System) | Nein | Nein | — |
Kette der Verantwortung | Vermeiden Sie die Kopplung zwischen dem Sender einer Anfrage und ihrem Empfänger, indem Sie mehr als einem Objekt die Möglichkeit geben, die Anfrage zu bearbeiten. Verketten Sie die empfangenden Objekte und leiten Sie die Anfrage entlang der Kette weiter, bis ein Objekt die Anfrage bearbeitet. | Ja | Nein | — |
Befehl | Kapselt eine Anfrage als Objekt und ermöglicht so die Parametrisierung von Clients mit unterschiedlichen Anfragen und die Einreihung oder Protokollierung von Anfragen. Es ermöglicht auch die Unterstützung von rückgängig zu machenden Operationen. | Ja | Nein | — |
Dolmetscher | Definieren Sie für eine Sprache eine Darstellung ihrer Grammatik zusammen mit einem Interpreter, der die Darstellung verwendet, um Sätze in der Sprache zu interpretieren. | Ja | Nein | — |
Iterator | Bietet eine Möglichkeit, auf die Elemente eines Aggregatobjekts sequentiell zuzugreifen, ohne die zugrunde liegende Darstellung offenzulegen. | Ja | Ja | — |
Vermittler | Definiert ein Objekt, das kapselt, wie eine Gruppe von Objekten interagiert. Mediator fördert die lose Kopplung, indem er verhindert, dass Objekte explizit aufeinander verweisen, und er ermöglicht es, dass ihre Interaktion unabhängig voneinander variiert. | Ja | Nein | — |
Memento | Erfasst und externalisiert den internen Zustand eines Objekts, ohne die Kapselung zu verletzen, so dass das Objekt später wieder in diesen Zustand versetzt werden kann. | Ja | Nein | — |
Null-Objekt | Vermeidung von Nullreferenzen durch Bereitstellung eines Standardobjekts. | Nein | Nein | — |
Beobachter oder Veröffentlichen/Abonnieren | Definieren Sie eine eins-zu-viele-Abhängigkeit zwischen Objekten, bei der eine Zustandsänderung in einem Objekt dazu führt, dass alle abhängigen Objekte automatisch benachrichtigt und aktualisiert werden. | Ja | Ja | — |
Diener | Definieren Sie gemeinsame Funktionen für eine Gruppe von Klassen. Das Servant-Pattern wird häufig auch als Hilfsklassen- oder Utility-Klassen-Implementierung für eine bestimmte Gruppe von Klassen bezeichnet. Die Hilfsklassen haben im Allgemeinen keine Objekte und verfügen daher über alle statischen Methoden, die auf verschiedene Arten von Klassenobjekten wirken. | Nein | Nein | — |
Spezifikation | Rekombinierbare Geschäftslogik in boolescher Form. | Nein | Nein | — |
Zustand | Erlaubt es einem Objekt, sein Verhalten zu ändern, wenn sich sein interner Zustand ändert. Das Objekt scheint seine Klasse zu wechseln. | Ja | Nein | — |
Strategie | Definieren Sie eine Familie von Algorithmen, kapseln Sie jeden einzelnen und machen Sie sie austauschbar. Die Strategie lässt den Algorithmus unabhängig von den Clients, die ihn verwenden, variieren. | Ja | Ja | — |
Schablonenmethode | Definieren Sie das Skelett eines Algorithmus in einer Operation, wobei Sie einige Schritte auf Unterklassen verschieben. Mit der Schablonenmethode können Unterklassen bestimmte Schritte eines Algorithmus umdefinieren, ohne die Struktur des Algorithmus zu verändern. | Ja | Ja | — |
Besucher | Stellt eine Operation dar, die auf Instanzen einer Menge von Klassen ausgeführt werden soll. Mit dem Visitor kann eine neue Operation definiert werden, ohne die Klassen der Elemente zu ändern, auf die sie wirkt. | Ja | Nein | — |
Fließende Schnittstelle | Entwerfen Sie eine API, die mit Methoden verkettet ist, so dass sie sich wie eine DSL liest. Jeder Methodenaufruf gibt einen Kontext zurück, über den der/die nächste(n) logische(n) Methodenaufruf(e) verfügbar gemacht werden. | Nein | Nein | — |
Gleichzeitigkeitsmuster
Name | Beschreibung | In POSA2 | Andere ⓘ |
---|---|---|---|
Aktives Objekt | Entkoppelt die Methodenausführung von den Methodenaufrufen, die sich in einem eigenen Kontrollfaden befinden. Das Ziel ist die Einführung von Gleichzeitigkeit durch asynchrone Methodenaufrufe und einen Scheduler für die Bearbeitung von Anfragen. | Ja | — |
Balking | Eine Aktion an einem Objekt nur dann ausführen, wenn sich das Objekt in einem bestimmten Zustand befindet. | Nein | — |
Eigenschaften binden | Kombination mehrerer Beobachter, um zu erzwingen, dass Eigenschaften in verschiedenen Objekten auf irgendeine Weise synchronisiert oder koordiniert werden. | Nein | — |
Rechenkern | Dieselbe Berechnung mehrmals parallel, mit ganzzahligen Parametern, die mit nicht verzweigten Zeigern in gemeinsam genutzten Arrays verwendet werden, z. B. GPU-optimierte Matrixmultiplikation oder neuronales Faltungsnetzwerk. | Nein | — |
Doppelt geprüfte Sperrung | Verringerung des Aufwands für die Erlangung einer Sperre, indem zunächst das Sperrkriterium (der "Sperrhinweis") auf unsichere Weise geprüft wird; nur wenn dies erfolgreich ist, wird die eigentliche Sperrlogik fortgesetzt.
Kann unsicher sein, wenn es in einigen Sprach-/Hardwarekombinationen implementiert ist. Daher kann es manchmal als Anti-Pattern betrachtet werden. |
Ja | — |
Ereignisbasierte Asynchronität | Behebt Probleme mit dem asynchronen Muster, die in Multithreading-Programmen auftreten. | Nein | — |
Bewachte Aussetzung | Verwaltet Operationen, für die sowohl eine Sperre als auch eine Vorbedingung erfüllt sein müssen, bevor die Operation ausgeführt werden kann. | Nein | — |
Join | Das Join-Muster bietet eine Möglichkeit, nebenläufige, parallele und verteilte Programme durch Nachrichtenübermittlung zu schreiben. Im Vergleich zur Verwendung von Threads und Sperren handelt es sich um ein High-Level-Programmiermodell. | Nein | — |
Sperren | Ein Thread setzt eine "Sperre" auf eine Ressource, die verhindert, dass andere Threads darauf zugreifen oder sie verändern. | Nein | PoEAA |
Messaging-Entwurfsmuster (MDP) | Ermöglicht den Austausch von Informationen (d.h. Nachrichten) zwischen Komponenten und Anwendungen. | Nein | — |
Monitor-Objekt | Ein Objekt, dessen Methoden dem gegenseitigen Ausschluss unterliegen, so dass verhindert wird, dass mehrere Objekte fälschlicherweise versuchen, es gleichzeitig zu benutzen. | Ja | — |
Reactor | Ein Reactor-Objekt bietet eine asynchrone Schnittstelle zu Ressourcen, die synchron behandelt werden müssen. | Ja | — |
Lese-Schreib-Sperre | Erlaubt den gleichzeitigen Lesezugriff auf ein Objekt, erfordert aber exklusiven Zugriff für Schreibvorgänge. Für Schreibvorgänge kann ein zugrunde liegender Semaphor verwendet werden, und ein Copy-on-write-Mechanismus kann verwendet werden oder auch nicht. | Nein | — |
Zeitplaner | Explizite Steuerung, wann Threads Single-Thread-Code ausführen dürfen. | Nein | — |
Thread-Pool | Eine Anzahl von Threads wird erstellt, um eine Anzahl von Aufgaben auszuführen, die normalerweise in einer Warteschlange organisiert sind. Normalerweise gibt es viel mehr Tasks als Threads. Kann als Spezialfall des Objektpool-Musters betrachtet werden. | Nein | — |
Thread-spezifischer Speicher | Statischer oder "globaler" Speicher, der für einen Thread lokal ist. | Ja | — |
Sichere Gleichzeitigkeit mit exklusiver Eigentümerschaft | Vermeidung der Notwendigkeit von nebenläufigen Mechanismen zur Laufzeit, da die exklusive Eigentümerschaft nachgewiesen werden kann. Dies ist eine bemerkenswerte Fähigkeit der Sprache Rust, aber die Überprüfung zur Kompilierzeit ist nicht das einzige Mittel, ein Programmierer wird solche Muster oft manuell in den Code einbauen - und dabei auf die Verwendung von Sperrmechanismen verzichten, weil der Programmierer davon ausgeht, dass auf eine bestimmte Variable niemals gleichzeitig zugegriffen werden wird. | Nein | — |
CPU-Atomoperationen | x86 und andere CPU-Architekturen unterstützen eine Reihe von atomaren Befehlen, die Speichersicherheit für die Änderung von und den Zugriff auf primitive Werte (Ganzzahlen) garantieren. Beispielsweise können zwei Threads einen Zähler sicher inkrementieren. Diese Fähigkeiten können auch zur Implementierung von Mechanismen für andere Gleichzeitigkeitsmuster (siehe oben) verwendet werden. Die Sprache C# verwendet für diese Fähigkeiten die Klasse Interlocked. | Nein | — |
Dokumentation
Die Dokumentation für ein Entwurfsmuster beschreibt den Kontext, in dem das Muster verwendet wird, die Kräfte innerhalb des Kontexts, die das Muster zu lösen versucht, und die vorgeschlagene Lösung. Es gibt kein einheitliches Standardformat für die Dokumentation von Entwurfsmustern. Vielmehr wurden von den verschiedenen Pattern-Autoren eine Vielzahl unterschiedlicher Formate verwendet. Martin Fowler zufolge sind jedoch bestimmte Musterformen bekannter als andere und werden daher häufig als Ausgangspunkt für neue Musterschreibversuche verwendet. Ein Beispiel für ein häufig verwendetes Dokumentationsformat ist das von Erich Gamma, Richard Helm, Ralph Johnson und John Vlissides in ihrem Buch Design Patterns verwendete. Es enthält die folgenden Abschnitte:
- Name und Klassifizierung des Musters: Ein beschreibender und eindeutiger Name, der hilft, das Muster zu identifizieren und darauf zu verweisen.
- Absicht: Eine Beschreibung des Ziels hinter dem Muster und des Grundes für seine Verwendung.
- Auch bekannt als: Andere Namen für das Muster.
- Motivation (Zwänge): Ein Szenario, bestehend aus einem Problem und einem Kontext, in dem dieses Muster verwendet werden kann.
- Anwendbarkeit: Situationen, in denen dieses Muster anwendbar ist; der Kontext für das Muster.
- Struktur: Eine grafische Darstellung des Musters. Zu diesem Zweck können Klassendiagramme und Interaktionsdiagramme verwendet werden.
- Teilnehmer: Eine Auflistung der Klassen und Objekte, die in dem Muster verwendet werden, und ihrer Rollen im Entwurf.
- Kollaboration: Eine Beschreibung, wie die im Muster verwendeten Klassen und Objekte miteinander interagieren.
- Konsequenzen: Eine Beschreibung der Ergebnisse, Nebeneffekte und Kompromisse, die durch die Verwendung des Musters entstehen.
- Implementierung: Eine Beschreibung der Implementierung des Patterns; der Lösungsteil des Patterns.
- Beispielcode: Eine Illustration, wie das Muster in einer Programmiersprache verwendet werden kann.
- Bekannte Verwendungen: Beispiele für reale Verwendungen des Musters.
- Verwandte Patterns: Andere Muster, die in irgendeiner Beziehung zu dem Muster stehen; Diskussion der Unterschiede zwischen dem Muster und ähnlichen Mustern. ⓘ
Kritik
Es wurde festgestellt, dass Entwurfsmuster möglicherweise nur ein Zeichen dafür sind, dass einige Funktionen in einer bestimmten Programmiersprache (z. B. Java oder C++) fehlen. Peter Norvig zeigt, dass 16 der 23 Muster im Buch Design Patterns (das sich hauptsächlich auf C++ konzentriert) in Lisp oder Dylan vereinfacht oder eliminiert sind (durch direkte Sprachunterstützung). Ähnliche Beobachtungen machten Hannemann und Kiczales, die mehrere der 23 Entwurfsmuster mit einer aspektorientierten Programmiersprache (AspectJ) implementierten und zeigten, dass Abhängigkeiten auf Code-Ebene bei der Implementierung von 17 der 23 Entwurfsmuster beseitigt wurden und dass aspektorientierte Programmierung die Implementierung von Entwurfsmustern vereinfachen kann. Siehe auch Paul Grahams Aufsatz "Revenge of the Nerds". ⓘ
Eine unangemessene Verwendung von Mustern kann die Komplexität unnötig erhöhen. ⓘ
Arten von Entwurfsmustern
Es gibt verschiedene Typen von Entwurfsmustern. Ursprünglich wurden folgende Typen vom Autorenquartett Gang of Four (GoF) unterschieden:
- Erzeugungsmuster (Creational Patterns)
- Dienen der Erzeugung von Objekten. Sie entkoppeln die Konstruktion eines Objekts von seiner Repräsentation. Die Objekterzeugung wird gekapselt und ausgelagert, um den Kontext der Objekterzeugung unabhängig von der konkreten Implementierung zu halten, gemäß der Regel: „Programmiere auf die Schnittstelle, nicht auf die Implementierung!“
- Strukturmuster (Structural Patterns)
- Erleichtern den Entwurf von Software durch vorgefertigte Schablonen für Beziehungen zwischen Klassen.
- Verhaltensmuster (Behavioral Patterns)
- Modellieren komplexes Verhalten der Software und erhöhen damit die Flexibilität der Software hinsichtlich ihres Verhaltens. ⓘ
Später kamen noch weitere Typen für diejenigen Entwurfsmuster, die in keine der drei genannten Typen passten, hinzu. Darunter beispielsweise:
- Muster für objektrelationale Abbildung
- Dienen der Ablage und dem Zugriff von Objekten und deren Beziehungen in einer relationalen Datenbank.
- Nachrichtenübermittlungsmuster (Messaging Patterns)
- Für die Erstellung, die Weiterleitung und die Umwandlung von Daten in Form von Nachrichten, inklusive der dazu benötigten Nachrichtenkanäle und Nachrichtenendpunkte, sowie Komponenten für die Systemverwaltung. ⓘ
Anforderungen und Nutzen
Ein gutes Muster sollte:
- ein oder mehrere Probleme lösen,
- ein erprobtes Konzept bieten,
- auf realen Designs basieren,
- die Benefits müssen den Nachteilen überwiegen
- über das rein Offensichtliche hinausgehen,
- den Benutzer in den Entwurfsprozess einbinden,
- Beziehungen aufzeigen, die tiefergehende Strukturen und Mechanismen eines Systems umfassen. ⓘ
Entwurfsmuster beinhalten in der Regel Referenzen auf andere Muster. Mithilfe dieser ist es möglich, Mustersprachen zu entwickeln. ⓘ
Der primäre Nutzen eines Entwurfsmusters liegt in der Beschreibung einer Lösung für eine bestimmte Klasse von Entwurfsproblemen. Weiterer Nutzen ergibt sich aus der Tatsache, dass jedes Muster einen Namen hat. Dies vereinfacht die Diskussion unter Entwicklern, da man abstrakt über eine Struktur sprechen kann. So sind etwa Software-Entwurfsmuster – im Gegensatz zu Idiomen – zunächst einmal unabhängig von der konkreten Programmiersprache. ⓘ
Wenn der Einsatz von Entwurfsmustern dokumentiert wird, ergibt sich ein weiterer Nutzen dadurch, dass durch die Beschreibung des Musters ein Bezug zur dort vorhandenen Diskussion des Problemkontextes und der Vor- und Nachteile der Lösung hergestellt wird. ⓘ
Nachteile
Der erfolgreiche Einsatz von Entwurfsmustern in der Vergangenheit kann dazu verleiten, die Entwurfsmuster als Wunderwaffe und Garant für gutes Design anzusehen. Unerfahrene Entwickler können geneigt sein, möglichst viele bekannte Muster zu verwenden, und dabei übersehen, dass in ihrem Fall vielleicht eine elegantere Lösung ohne den Einsatz von Mustern möglich wäre. Entwurfsmuster garantieren nicht, dass der Entwurf gut ist. Insofern ist die Anwendung zu vieler oder ungeeigneter Entwurfsmuster ein Antimuster. ⓘ
Musterkataloge
Liste von Mustern
Die folgende Liste enthält Entwurfsmuster der Gang of Four, funktionale Verhaltensmuster von Stuart Sierra sowie andere Entwurfsmuster aus anderen Katalogen. Die ersten drei Abschnitte stellen die Teilmengen dar, in die die Entwurfsmuster im Buch Design Patterns kategorisiert wurden. Der vierte Abschnitt enthält Muster für die objektrelationale Abbildung die insbesondere von Martin Fowler geprägt wurden. Der fünfte Abschnitt enthält Entwurfsmuster für die Kommunikation zwischen Anwendungen, die von Gregor Hope und Bobby Woolf im Buch Enterprise Integration Patterns beschrieben wurden. Der sechste Abschnitt enthält Entwurfsmuster, die sich in keine der ersten fünf Abschnitte einordnen lassen. Die Liste ist nicht vollständig und überschneidet sich teilweise mit Architekturmustern. ⓘ
1. Erzeugungsmuster (englisch creational patterns)
- Erbauer (Builder)
- Fabrikmethode (Factory method)
- Multiton (Multiton)
- Prototyp (Prototype)
- Singleton (Singleton)
2. Strukturmuster (englisch structural design patterns)
- Container (Container)
- Dekorierer (Decorator)
- Fassade (Facade)
- Fliegengewicht (Flyweight)
- Kompositum (Composite oder Whole-Part)
- Stellvertreter (Proxy)
- Half Object Plus Protocol
3. Verhaltensmuster (englisch behavioral design patterns)
- Interceptor (Interceptor)
- Interpreter (Interpreter)
- Iterator (Iterator)
- Kommando (Command)
- Memento (Memento)
- Nullobjekt (Null Object)
- Schablonenmethode (Template method)
- Strategie (Strategy)
- Vermittler (Mediator)
- Zustand (State)
- Zuständigkeitskette (Chain of responsibility)
- State/Event
- Consequences
- Accumulator
- MapReduce
- Reduce/Combine
- Rekursive Erweiterung
- Software Pipelining
- Prozess Wrapper
- Token
- Page Object
4. Muster für objektrelationale Abbildung
- Datentransferobjekt (Data transfer object)
- Table Data Gateway
- Row Data Gateway
- Active Record
- Unit of Work
- Identity Map
- Lazy Loading
- Identity Field
- Dependent Mapping
- Embedded Value
- Serialized LOB
- Inheritance Mapper
- Metadata Mapping
- Query Object
- Command-Query-Responsibility-Segregation
5. Nachrichtenübermittlungsmuster (Messaging Patterns)
- Messaging Mapper
- Transactional Client
- Polling Consumer
- Event-driven Consumer
- Competing Consumers
- Message Dispatcher
- Selective Consumer
- Durable Subscriber
- Idempotent Receiver
- Service Activator
- Message
- Command Message
- Document Message
- Event Message
- Request-Reply
- Return Address
- Correlation Identifier
- Message Sequence
- Message Expiration
- Format Indicator
- Message Channel
- Point-to-Point Channel
- Publisher-Subscriber Channel
- Datatype Channel
- Invalid Message Channel
- Dead Letter Channel
- Guaranteed Delivery
- Channel Adapter
- Messaging Bridge
- Message Bus
- Pipes-and-Filters
- Message Router
- Content-based Router
- Message Filter
- Dynamic Router
- Recipient List
- Splitter
- Aggregator
- Resequencer
- Composed Message Processor
- Scatter-Gather
- Routing Slip
- Process Manager
- Message Broker
- Message Translator
- Envelope Wrapper
- Content Enricher
- Content Filter
- Claim Check
- Normalizer
- Canonical Data Model
- Control Bus
- Detour
- Wire Tap
- Message History
- Message Store
- Smart Proxy
- Test Message
- Channel Purger
6. Weitere Muster
- Extension Interface
- Fluent Interface
- Inversion of Control
- Transaction Script
- Table Module
- Page Controller
- Template View
- Transform View
- Two-Step View
- Application Controller
- Remote Facade
- Locks
- Session States
- Repository
- Value Object
- Registry ⓘ
Antimuster
Wo Entwurfsmuster in der Software-Entwicklung allgemein übliche und bekannte Lösungsansätze sind, um Probleme zu lösen, so sind Antimuster Negativ-Beispiele von bereits durchgeführten Lösungen, die Hinweise darauf geben, welche Fehler vermieden werden sollten. ⓘ
Nachdem bei der Softwareentwicklung immer mehr von positiven Erfahrungen von erfolgreich abgeschlossenen Aufgabenstellungen profitiert wurde, konzentrierte man sich auch darauf, die Negativbeispiele, also wiederkehrende Fehler bei der Software-Entwicklung, zu identifizieren und zu dokumentieren. ⓘ