Kann jemand bitte in Laienbegriffen erklären?
Designmuster sind keine wirklichen "Laien" -Konzepte, aber ich werde versuchen, es so klar wie möglich zu machen. Jedes Entwurfsmuster kann in drei Dimensionen betrachtet werden:
- Das Problem, das das Muster löst;
- Die statische Struktur des Musters (Klassendiagramm);
- Die Dynamik des Musters (Sequenzdiagramme).
Vergleichen wir Zustand und Strategie.
Problem, das das Muster löst
Der Status wird in einem von zwei Fällen verwendet [GoF-Buch S. 306] :
- Das Verhalten eines Objekts hängt von seinem Status ab und es muss sein Verhalten zur Laufzeit abhängig von diesem Status ändern.
- Operationen haben große, mehrteilige bedingte Anweisungen, die vom Status des Objekts abhängen. Dieser Zustand wird normalerweise durch eine oder mehrere aufgezählte Konstanten dargestellt. Oft enthalten mehrere Operationen dieselbe bedingte Struktur. Das Zustandsmuster ordnet jeden Zweig der Bedingung einer separaten Klasse zu. Auf diese Weise können Sie den Status des Objekts als eigenständiges Objekt behandeln, das unabhängig von anderen Objekten variieren kann.
Wenn Sie sicherstellen möchten, dass Sie tatsächlich das Problem haben, das das Zustandsmuster löst, sollten Sie in der Lage sein, die Zustände des Objekts mithilfe einer endlichen Zustandsmaschine zu modellieren . Ein angewandtes Beispiel finden Sie hier .
Jeder Zustandsübergang ist eine Methode in der Zustandsschnittstelle. Dies bedeutet, dass Sie für ein Design über Zustandsübergänge ziemlich sicher sein müssen, bevor Sie dieses Muster anwenden. Andernfalls müssen beim Hinzufügen oder Entfernen von Übergängen die Schnittstelle und alle Klassen, die sie implementieren, geändert werden.
Ich persönlich fand dieses Muster nicht so nützlich. Sie können Finite-State-Maschinen jederzeit mithilfe einer Nachschlagetabelle implementieren (dies ist keine OO-Methode, funktioniert aber recht gut).
Die Strategie wird für Folgendes verwendet [GoF-Buch S. 316] :
- Viele verwandte Klassen unterscheiden sich nur in ihrem Verhalten. Strategien bieten eine Möglichkeit, eine Klasse mit einem von vielen Verhaltensweisen zu konfigurieren.
- Sie benötigen verschiedene Varianten eines Algorithmus. Beispielsweise können Sie Algorithmen definieren, die unterschiedliche räumliche / zeitliche Kompromisse widerspiegeln. Strategien können verwendet werden, wenn diese Varianten als Klassenhierarchie von Algorithmen implementiert sind [HO87].
- Ein Algorithmus verwendet Daten, über die Clients nichts wissen sollten. Verwenden Sie das Strategiemuster, um zu vermeiden, dass komplexe, algorithmische Datenstrukturen verfügbar gemacht werden.
- Eine Klasse definiert viele Verhaltensweisen, und diese werden in ihren Operationen als mehrere bedingte Anweisungen angezeigt. Verschieben Sie verwandte bedingte Zweige anstelle vieler Bedingungen in ihre eigene Strategieklasse.
Der letzte Fall, in dem die Strategie angewendet werden soll, bezieht sich auf ein Refactoring, das als Ersetzen bedingt durch Polymorphismus bezeichnet wird .
Zusammenfassung: Staat und Strategie lösen sehr unterschiedliche Probleme. Wenn Ihr Problem nicht mit einer endlichen Zustandsmaschine modelliert werden kann, ist das wahrscheinliche Zustandsmuster nicht geeignet. Wenn es bei Ihrem Problem nicht darum geht, Varianten eines komplexen Algorithmus zu kapseln, gilt die Strategie nicht.
Statische Struktur des Musters
Der Status hat die folgende UML-Klassenstruktur:
Die Strategie hat die folgende UML-Klassenstruktur:
Zusammenfassung: In Bezug auf die statische Struktur sind diese beiden Muster größtenteils identisch. Tatsächlich sind Mustererkennungswerkzeuge wie dieses der Ansicht, dass " die Struktur der [...] Muster identisch ist und ihre Unterscheidung durch einen automatischen Prozess verhindert (z. B. ohne Bezugnahme auf konzeptionelle Informationen) ".
Es kann jedoch einen großen Unterschied geben, wenn ConcreteStates die Zustandsübergänge selbst bestimmen (siehe die Assoziationen " möglicherweise bestimmen " im obigen Diagramm). Dies führt zu einer Kopplung zwischen konkreten Zuständen. Beispiel (siehe nächster Abschnitt), Status A bestimmt den Übergang zu Status B. Wenn die Context-Klasse den Übergang zum nächsten konkreten Status entscheidet, verschwinden diese Abhängigkeiten.
Dynamik des Musters
Wie im Abschnitt oben Problem erwähnt, Staat bedeutet , dass Verhaltensänderungen zur Laufzeit in Abhängigkeit von einem gewissen Zustand eines Objekts. Daher ist der Begriff der staatlichen transitioning Anwendung findet, wie bei der Beziehung der diskutierten finite Zustandsmaschine . [GoF] erwähnt, dass Übergänge entweder in den ConcreteState-Unterklassen oder an einem zentralen Ort (z. B. einem tabellenbasierten Ort) definiert werden können.
Nehmen wir eine einfache endliche Zustandsmaschine an:
Angenommen, die Unterklassen entscheiden über den Statusübergang (durch Rückgabe des nächsten Statusobjekts), sieht die Dynamik ungefähr so aus:
Um die Dynamik der Strategie zu zeigen , ist es nützlich, ein echtes Beispiel auszuleihen .
Zusammenfassung : Jedes Muster verwendet einen polymorphen Aufruf, um je nach Kontext etwas zu tun. Im Zustandsmuster bewirkt der polymorphe Aufruf (Übergang) häufig eine Änderung des nächsten Zustands . Im Strategiemuster ändert der polymorphe Anruf normalerweise nicht den Kontext (z. B. bedeutet das einmalige Bezahlen mit Kreditkarte nicht, dass Sie das nächste Mal mit PayPal bezahlen). Auch hier wird die Dynamik des Zustandsmusters durch die entsprechende Fininte-Zustandsmaschine bestimmt, was (für mich) für die korrekte Anwendung dieses Musters wesentlich ist.