Ich füge eine Kapselungshierarchietabelle mit mehreren GoF-Entwurfsmustern hinzu, um die Unterschiede zwischen diesen beiden Mustern zu erläutern. Hoffentlich zeigt es besser, was jeder verkapselt, damit meine Erklärung sinnvoller ist.
Zunächst listet die Hierarchie den Bereich auf, für den ein bestimmtes Muster anwendbar ist, oder das geeignete Muster, mit dem eine bestimmte Detailebene gekapselt werden kann, je nachdem, auf welcher Seite der Tabelle Sie beginnen.
Wie Sie der Tabelle entnehmen können, verbirgt ein Strategiemusterobjekt Details der Implementierung eines Algorithmus, sodass die Verwendung eines anderen Strategieobjekts dieselbe Funktionalität auf unterschiedliche Weise ausführt. Jedes Strategieobjekt kann für einen bestimmten Faktor optimiert sein oder mit einem anderen Parameter arbeiten. Durch die Verwendung einer gemeinsamen Schnittstelle kann der Kontext sicher mit beiden arbeiten.
Das Befehlsmuster kapselt einen viel kleineren Detaillierungsgrad als ein Algorithmus. Es codiert die Details, die zum Senden einer Nachricht an ein Objekt erforderlich sind: Empfänger, Selektor und Argumente. Der Vorteil der Objektivierung eines so kleinen Teils der Prozessausführung besteht darin, dass solche Nachrichten allgemein zu verschiedenen Zeitpunkten oder an verschiedenen Orten aufgerufen werden können, ohne dass ihre Details fest codiert werden müssen. Damit können Nachrichten ein- oder mehrmals aufgerufen oder an verschiedene Teile des Systems oder an mehrere Systeme weitergeleitet werden, ohne dass die Details eines bestimmten Aufrufs vor der Ausführung bekannt sein müssen.
Wie es für Entwurfsmuster typisch ist, müssen nicht alle Implementierungen im Detail identisch sein, um den Musternamen zu tragen. Details können in der Implementierung und in den im Objekt codierten Daten im Vergleich zu Methodenargumenten variieren.
Strategien kapseln Algorithmen. Befehle trennen den Absender vom Empfänger einer Anfrage, sie verwandeln eine Anfrage in ein Objekt.
Wenn es sich um einen Algorithmus handelt, verwenden Sie eine Strategie. Wenn Sie den Aufruf einer Methode von ihrer Ausführung trennen müssen, verwenden Sie einen Befehl. Befehle werden häufig verwendet, wenn Sie Nachrichten für eine spätere Verwendung in die Warteschlange stellen, z. B. eine Aufgabe oder eine Transaktion.
quelle
Beantwortung einer sehr alten Frage. (sieht jemand die letzten Antworten anstatt die meisten Stimmen?)
Aufgrund der Ähnlichkeiten ist es eine berechtigte Verwirrung. Sowohl Strategie- als auch Befehlsmuster verwenden die Kapselung . Aber das macht sie nicht gleich.
Der Hauptunterschied besteht darin, zu verstehen, was gekapselt ist. Das OO-Prinzip, von dem beide Muster abhängen, lautet: Verkapseln, was variiert .
Im Falle einer Strategie variiert der Algorithmus . Beispielsweise kann ein Strategieobjekt in eine XML-Datei ausgeben, während das andere beispielsweise in JSON ausgibt. Verschiedene Algorithmen werden in verschiedenen Klassen aufbewahrt ( gekapselt ). So einfach ist das.
Im Falle eines Befehls variiert die Anforderung selbst. Anfrage kann von
File Menu > Delete
oderRight Click > Context Menu > Delete
oder kommenJust Delete Button pressed
. Alle drei Fälle können 3 Befehlsobjekte des gleichen Typs generieren. Diese Befehlsobjekte stellen nur 3 Löschanforderungen dar. kein Löschalgorithmus. Da es sich bei Anfragen jetzt um eine Reihe von Objekten handelt, können wir sie problemlos verwalten. Plötzlich wird es trivial, Funktionen wie Rückgängig oder Wiederherstellen bereitzustellen.Es spielt keine Rolle, wie der Befehl die angeforderte Logik implementiert. Beim Aufruf von execute () kann ein Algorithmus implementiert werden, um das Löschen auszulösen, oder er kann ihn sogar an andere Objekte delegieren oder sogar an eine Strategie delegieren. Es ist nur ein Implementierungsdetail des Befehlsmusters. Aus diesem Grund wird es als Befehl bezeichnet, obwohl es keine höfliche Art ist, Folgendes anzufordern : -)
Vergleichen Sie es mit der Strategie; Dieses Muster befasst sich nur mit der tatsächlichen Logik , die ausgeführt wird. Wenn wir das tun, hilft es, verschiedene Verhaltenskombinationen mit einer minimalen Anzahl von Klassen zu erzielen und so eine Klassenexplosion zu verhindern.
Ich denke, Command hilft uns, unser Verständnis von Kapselung zu erweitern, während Strategie die natürliche Verwendung von Kapselung und Polymorphismus ermöglicht.
quelle
Ich sehe es so, dass Sie mehrere Möglichkeiten haben, dasselbe zu tun. Jede davon ist eine Strategie, und zur Laufzeit bestimmt etwas, welche Strategie ausgeführt wird.
Versuchen Sie es zuerst mit StrategyOne. Wenn die Ergebnisse nicht gut genug sind, versuchen Sie es mit StrategyTwo ...
Befehle sind an bestimmte Dinge gebunden, die passieren müssen, wie z. B. TryToWalkAcrossTheRoomCommand. Dieser Befehl wird immer dann ausgelöst, wenn ein Objekt versuchen soll, durch den Raum zu gehen. In diesem Objekt werden jedoch möglicherweise StrategyOne und StrategyTwo ausgeführt, um zu versuchen, durch den Raum zu gehen.
Kennzeichen
quelle
Ich könnte meiner Meinung nach falsch liegen, aber ich behandle den Befehl als Funktion zum Ausführen oder als Reaktion. Es sollten mindestens zwei Spieler vorhanden sein: derjenige, der die Aktion anfordert, und derjenige, der die Aktion ausführt. Die grafische Benutzeroberfläche ist ein typisches Beispiel für ein Befehlsmuster:
Der Befehl ist normalerweise an einen bestimmten Bereich oder Geschäftsbereich gebunden, jedoch nicht erforderlich: Möglicherweise verfügen Sie über Befehle, die eine Rechnung ausstellen, eine Rakete starten oder eine Datei entfernen, die dieselbe Schnittstelle (z. B. eine einzelne
execute()
Methode) in einer Anwendung implementiert . Oft sind Befehle in sich geschlossen, sodass sie vom Executor nichts benötigen, um die beabsichtigte Aufgabe zu verarbeiten (alle erforderlichen Informationen werden zum Zeitpunkt der Erstellung angegeben). Manchmal sind Befehle kontextsensitiv und sollten in der Lage sein, diesen Kontext zu erkennen (Der Backspace- Befehl sollte die Caret-Position im Text kennen, um das vorherige Zeichen korrekt zu entfernen. Der Rollback- Befehl sollte die aktuelle Transaktion für das Rollback ermitteln. ...).Die Strategie ist etwas anders: Sie ist eher an einen Bereich gebunden. Die Strategie kann eine Regel zum Formatieren eines Datums (in UTC? Gebietsschemaspezifisch?) ("Datumsformatierer" -Strategie) oder zum Berechnen eines Quadrats für eine geometrische Figur ("Quadratrechner" -Strategie) definieren. Strategien sind in diesem Sinne Objekte im Fliegengewicht, die etwas als Eingabe ("Datum", "Zahl", ...) verwenden und auf ihrer Grundlage eine Entscheidung treffen. Vielleicht nicht die beste, aber gutes Beispiel für Strategie ist eine mit verbundenen
javax.xml.transform.Source
Schnittstelle: je nachdem , ob das übergebene Objekt istDOMSource
oderSAXSource
oderStreamSource
die Strategie (= XSLT Transformator in diesem Fall) werden unterschiedliche Regeln gelten , sie zu verarbeiten. Die Implementierung kann einfach seinswitch
oder ein Muster der Verantwortungskette beinhalten .In der Tat haben diese beiden Muster etwas gemeinsam: Befehle und Strategien kapseln Algorithmen innerhalb desselben semantischen Bereichs.
quelle
Befehl:
Grundlegende Bestandteile:
execute()
Arbeitsablauf:
Client ruft Invoker => Invoker ruft ConcreteCommand => ConcreteCommand- Aufrufe auf Receiver- Methode auf, die die abstrakte Command- Methode implementiert .
Vorteil : Änderungen an Befehl und Empfänger durch den Client sind nicht betroffen. Invoker bietet eine lose Kopplung zwischen Client und Empfänger. Sie können mehrere Befehle mit demselben Invoker ausführen.
Mit dem Befehlsmuster können Sie einen Befehl auf verschiedenen Empfängern ausführen,indem Sie denselben Invoker verwenden . Invoker kennt den Empfängertyp nicht
Schauen Sie sich zum besseren Verständnis der Konzepte diesen JournalDev- Artikel von Pankaj Kumar und den dzone- Artikel an von James Sugrue zusätzlich zum Wikipedia-Link.
Sie können das Befehlsmuster verwenden , um
Entkoppeln Sie den Aufrufer und den Befehlsempfänger
Rückrufmechanismus implementieren
Implementieren Sie die Funktionen zum Rückgängigmachen und Wiederherstellen
Pflegen Sie eine Befehlsgeschichte
java.lang.Thread
ist eine gute Umsetzung von Befehlsmustern. Sie können Thread als Aufrufer und Klasse behandeln, die Runnable als ConcreteCommonad / Receiver und dierun()
Methode als Befehl implementieren .Die Version des Befehlsmusters zum Rückgängigmachen / Wiederherstellen kann im Artikel von Theodore Norvell gelesen werden
Strategie:
Das Strategiemuster ist sehr einfach zu verstehen. Verwenden Sie dieses Muster, wenn
Sie haben mehrere Implementierungen für einen Algorithmus, und die Implementierung des Algorithmus kann sich zur Laufzeit abhängig von bestimmten Bedingungen ändern .
Nehmen Sie ein Beispiel für die Tarifkomponente des Airline-Buchungssystems
Die Fluggesellschaften möchten in verschiedenen Zeiträumen unterschiedliche Tarife anbieten - Spitzen- und Nebenzeiten. An Tagen außerhalb der Hauptverkehrszeiten möchte es die Nachfrage durch attraktive Rabatte anregen.
Wichtige Erkenntnisse zum Strategiemuster :
Verwandte Beiträge mit Codebeispielen:
Verwenden des Befehlsentwurfsmusters
Beispiel aus der Praxis für das Strategiemuster
quelle
Für mich liegt der Unterschied in der Absicht. Die Implementierungen beider Muster sind ziemlich ähnlich, haben aber unterschiedliche Zwecke:
Bei einer Strategie weiß die Komponente, die das Objekt verwendet, was das Objekt tut (und verwendet es, um einen Teil seiner eigenen Arbeit auszuführen), aber es ist ihm egal, wie es es tut.
Bei einem Befehl weiß die Komponente, die das Objekt verwendet, weder, was der Befehl tut, noch wie er es tut - sie weiß nur, wie sie ihn aufruft. Die Aufgabe des Anrufers besteht lediglich darin, den Befehl auszuführen. Die vom Befehl ausgeführte Verarbeitung ist nicht Teil der Kernarbeit des Anrufers.
Dies ist der Unterschied - weiß das Objekt, das die Komponente verwendet, tatsächlich oder kümmert es sich darum, was die Komponente tut? Meistens kann dies basierend darauf bestimmt werden, ob das Musterobjekt einen Wert an seinen Aufrufer zurückgibt. Wenn sich der Aufrufer darum kümmert, was das Musterobjekt tut, möchte er wahrscheinlich, dass es etwas zurückgibt, und es wird eine Strategie sein. Wenn es sich nicht um einen Rückgabewert handelt, handelt es sich wahrscheinlich um einen Befehl (Hinweis: So etwas wie ein Java Callable ist immer noch ein Befehl, da der Aufrufer den Wert nicht zurückgibt, obwohl er einen Wert zurückgibt - er gibt ihn einfach zurück zu dem, was ursprünglich den Befehl geliefert hat).
quelle