Objektorientierte Entwurfsmuster anhand von Praxisbeispielen erläutert
Verhaltensmuster
Diese Art von Mustern befassen sich mit der Kommunikation zwischen Objekten. In den meisten Fällen werden die Abhängigkeiten zwischen kommunizierenden Objekten durch diese Muster reduziert, was zu einem besseren Softwaredesign führt.
Verantwortungskette
Dieses Muster erstellt eine Kette von Empfängerobjekten für eine Anforderung. Es vermeidet die Kopplung des Absenders einer Anfrage an den Empfänger und gibt mehreren Objekten die Möglichkeit, die Anfrage zu bearbeiten. Empfangende Objekte sind miteinander verknüpft., Im folgenden Beispiel wird eine Kette von Middleware-Einheiten aufgebaut. Die Anfrage, die E-Mail und Passwort enthält, wird in der Kette weitergeleitet. Neue Elemente in der Kette können einfach hinzugefügt werden.
Befehl
Im Befehlsmuster wird ein Objekt verwendet, um alle Informationen einzukapseln, die zum Ausführen einer Aktion oder zum Auslösen eines Ereignisses zu einem späteren Zeitpunkt erforderlich sind. Wie unten gezeigt, definiert ActionOpen die Aktion sowie das Objekt, für das die Aktion ausgeführt wird., Weitere Informationen werden nicht benötigt und ein anderes Objekt, hier Menü, kann die Aktion ausführen.
Interpreter
Das Interpreter-Muster definiert eine Darstellung für die Grammatik einer Sprache und bietet die Möglichkeit, Sätze dieser Sprache zu interpretieren. Im folgenden Codeausschnitt kann ein Plus-Objekt „operand1 + operand2“ interpretieren und weiß, was mit diesem Ausdruck zu tun ist. Weitere Dolmetscher können hinzugefügt werden, ohne die Struktur zu stark zu ändern. Der Parser verwendet dann Interpreter, um Eingaben zu verstehen.,
Iterator
Der Iterator wird zum Durchlaufen eines Datencontainers verwendet, um auf die Elemente des Containers zuzugreifen, ohne die zugrunde liegende Struktur kennen zu müssen. Außerdem können neue Traversalvarianten hinzugefügt werden, ohne die Schnittstelle der Objekte oder die Datenstruktur selbst zu ändern.
Die ChannelSurfer, unten abgebildet, können Kanäle in aufeinanderfolgender Weise zugreifen. Das RemoteControl-Objekt muss sich nicht darum kümmern, wie die Kanäle organisiert sind. Ein RandomChannelSurfer kann beispielsweise problemlos hinzugefügt werden.,
Mediator
Wenn zwei oder mehr Objekte zu kooperieren, das Mediator-Muster angewendet werden kann. Besonders wenn sich die Objekte nicht kennen, wenn sie nicht eng gekoppelt sein sollten oder ihre Interaktion komplex ist, kann dieses Muster helfen.
Im folgenden Beispiel ist eine Interaktion zwischen UI-Elementen erforderlich. Diese Interaktion erfolgt über den AuthenticationDialog als Mediator. Auf diese Weise wird die Interaktion nicht in einem der teilnehmenden Objekte definiert, sondern in den Mediator extrahiert.,
Memento
Das Memento-Muster ist nützlich, wenn ein bestimmter Status eines Objekts für die spätere Verwendung gespeichert werden soll. Dadurch wird die Kapselung der Implementierungsdetails dieses Objekts nicht verletzt. Es kann beispielsweise für die Implementierung eines Rückgängig-Mechanismus verwendet werden.
Beobachter
In the observer pattern observer-Objekte abonnieren, um ein beobachtbares Objekt, um jedes mal benachrichtigt werden die beobachtbaren änderungen seiner Daten., Beobachter sind lose gekoppelt und können zur Laufzeit hinzugefügt und entfernt werden.
In Bezug darauf, wie der Beobachter schließlich die Daten aus dem observable erhält, gibt es zwei Varianten: Push und Pull. Der folgende Code zeigt die Pull-Variante, die flexibler ist, da in diesem Fall das Observable nicht wissen muss, wie der Beobachter die Daten empfangen möchte, sondern der Beobachter die Daten wie gewünscht abrufen kann.
State
Mit dem Statusmuster kann ein Objekt sein Verhalten ändern, wenn sich sein interner Status ändert., Dieses Muster ähnelt dem Strategiemuster, wird jedoch in diesem Fall intern entschieden, wie sich die Objekte verhalten. Dies ist besonders hilfreich, wenn komplexe Bedingungen definieren, wie sich das Objekt verhalten soll. Neue Zustände können unabhängig von bestehenden Zuständen hinzugefügt werden.
Strategie
Im Kontext des Strategiemusters gibt es mehrere Varianten für einen Algorithmus, bei denen eine Variante zur Laufzeit ausgeführt werden soll.,
Im folgenden Beispiel kann ein Compressor-Objekt mit einem von zwei verschiedenen Algorithmen verwendet werden, die zur Laufzeit definiert sind. Die Methode, die die Aktion ausführt (createArchive), wendet dann den ausgewählten Algorithmus an.
Template
Das Template-Muster definiert eine Struktur für Unterklassen, in denen Schritte eines Algorithmus und deren Reihenfolge definiert sind. Dadurch wird sichergestellt, dass die Unterklassen genau den gleichen Schritten folgen und eine bessere Übersicht und Konsistenz bieten., Außerdem können Standardimplementierungen für Schritte definiert werden, die von Unterklassen überschrieben werden können.
Wie unten gezeigt, folgen alle Parser, die von DataParser erben, genau den gleichen Schritten, wenn parse() ausgeführt wird. Dies stellt beispielsweise sicher, dass alle Parser die Dateien schließen und den Status protokollieren.
Visitor
Das Besuchermuster ermöglicht es, zur Laufzeit eine oder mehrere Operationen auf eine Reihe von Objekten anzuwenden, ohne dass die Operationen eng mit der Objektstruktur gekoppelt sind.,
Damit können Sie Double dispatch implementieren, bei dem ein Funktionsaufruf für verschiedene konkrete Funktionen vom Laufzeittyp zweier Objekte abhängt. Im folgenden Beispiel gibt es einerseits Routenelemente und andererseits Besucherobjekte, die jeweils unterschiedliche Funktionen auf den Routenelementen ausführen. Wenn in Zukunft mehr Besucher hinzugefügt werden, muss sich das Routenelement nicht ändern.