it-swarm.com.de

Verwenden eines Strategiemusters und eines Befehlsmusters

Beide Entwurfsmuster kapseln einen Algorithmus und entkoppeln Implementierungsdetails von ihren aufrufenden Klassen. Der einzige Unterschied, den ich erkennen kann, ist, dass das Strategiemuster Parameter für die Ausführung übernimmt, das Befehlsmuster jedoch nicht.

Es scheint mir, dass das Befehlsmuster erfordert, dass alle Informationen für die Ausführung verfügbar sind, wenn es erstellt wird, und dass es in der Lage ist, seinen Aufruf zu verzögern (möglicherweise als Teil eines Skripts). 

Welche Bestimmungen bestimmen, ob das eine oder das andere Muster verwendet wird? 

118
Extrakun

Ich füge eine Kapselungs-Hierarchietabelle mit mehreren GoF-Entwurfsmustern ein, um die Unterschiede zwischen diesen beiden Mustern zu erklären. Hoffentlich veranschaulicht es besser, was jeder einkapselt, so dass meine Erklärung sinnvoller ist.

Zunächst wird in der Hierarchie der Gültigkeitsbereich aufgeführt, für den ein bestimmtes Muster gilt, oder das geeignete Muster, das zum Verkapseln einer gewissen Detailebene verwendet werden soll, je nachdem, auf welcher Seite der Tabelle Sie beginnen.

design pattern encapsulation hierarchy table

Wie Sie der Tabelle entnehmen können, blendet ein Strategiemusterobjekt Details der Implementierung eines Algorithmus aus. Die Verwendung eines anderen Strategieobjekts führt also dieselbe Funktionalität aus, jedoch auf andere Weise. Jedes Strategieobjekt kann für einen bestimmten Faktor optimiert sein oder mit einem anderen Parameter arbeiten. und durch die Verwendung einer gemeinsamen Schnittstelle kann der Kontext mit beiden sicher arbeiten.

Das Befehlsmuster enthält eine viel geringere Detailstufe 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 solchen winzigen Teils der Prozessausführung besteht darin, dass solche Nachrichten zu verschiedenen Zeitpunkten oder Orten auf allgemeine Weise aufgerufen werden können, ohne dass deren Details hart codiert werden müssen. Es ermöglicht das einmalige oder mehrmalige Aufrufen von Nachrichten oder das Weiterleiten an verschiedene Teile des Systems oder an mehrere Systeme, ohne dass die Details eines bestimmten Aufrufs vor der Ausführung bekannt sein müssen. 

Wie für Designmuster typisch, müssen nicht alle Implementierungen identisch sein, um den Musternamen zu tragen. Details können sich in der Implementierung und in den Daten, die im Objekt codiert sind, als Methodenargumente unterscheiden.

91
Huperniketes

Strategien kapseln Algorithmen. Befehle trennen den Sender vom Empfänger einer Anfrage. Sie wandeln eine Anfrage in ein Objekt um. 

Wenn es sich um einen Algorithmus handelt, wie etwas getan wird, 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 eine Warteschlange stellen, z. B. eine Aufgabe oder eine Transaktion. 

48
Paul Rubel

Eine sehr alte Frage beantworten. (Sehen jemand die neuesten Antworten anstatt der meisten Stimmen?)

Es ist eine gültige Verwirrung, wegen der Ähnlichkeiten zu haben. Sowohl Strategie- als auch Befehlsmuster verwenden encapsulation . Aber das macht sie nicht gleich.

Der Hauptunterschied besteht darin zu verstehen, was gekapselt ist. Das OO -Prinzip, auf das beide Muster angewiesen sind, ist Encapsulate, was variiert .

Im Falle einer Strategie variiert Algorithmus . Ein Strategieobjekt weiß beispielsweise, wie es in eine XML-Datei ausgegeben werden soll, während das andere zum Beispiel in JSON ausgegeben wird. Unterschiedliche Algorithmen werden in verschiedenen Klassen gehalten ( encapsulated ). So einfach ist das.

Im Falle eines Befehls variiert das request sich selbst. Die Anfrage kann von File Menu > Delete oder Right Click > Context Menu > Delete oder Just Delete Button pressed stammen. In allen drei Fällen können 3 Befehlsobjekte desselben Typs generiert werden. Diese Befehlsobjekte repräsentieren nur 3 Löschanforderungen. Löschalgorithmus nicht. Da Anfragen jetzt mehrere Objekte sind, könnten wir sie problemlos verwalten. Plötzlich wird es trivial, Funktionen wie Rückgängig machen oder Wiederherstellen bereitzustellen.

Es spielt keine Rolle, wie der Befehl die angeforderte Logik implementiert. Beim Aufruf von execute () kann es einen Algorithmus implementieren, um das Löschen auszulösen, oder es kann es sogar an andere Objekte delegieren oder sogar an eine Strategie delegieren. Es ist nur ein Implementierungsdetail des Befehlsmusters. Aus diesem Grund wird es als command bezeichnet, obwohl es keine höfliche Art zu request : - ist.

Vergleichen Sie es mit der Strategie. Dieses Muster befasst sich nur mit der tatsächlichen logic , die ausgeführt wird. Wenn wir das tun, hilft es, verschiedene Verhaltenskombinationen mit einem minimalen Satz von Klassen zu erreichen, wodurch eine Klassenexplosion verhindert wird.

Ich denke, Command hilft uns dabei, unser Verständnis der Einkapselung zu erweitern, während die Strategie die natürliche Nutzung der Einkapselung und des Polymorphismus ermöglicht.

23
rpattabi

Ich betrachte es so, dass Sie mehrere Möglichkeiten haben, das Gleiche zu tun. Jede dieser Strategien ist eine Strategie. Etwas zur Laufzeit bestimmt, welche Strategie ausgeführt wird.

Versuchen Sie es zuerst mit StrategyOne. Wenn die Ergebnisse nicht gut genug sind, versuchen Sie mit StrategyTwo ...

Befehle sind an bestimmte Dinge gebunden, die wie TryToWalkAcrossTheRoomCommand geschehen müssen. Dieser Befehl wird immer dann ausgelöst, wenn ein Objekt versucht, durch den Raum zu laufen. In diesem Fenster können jedoch auch StrategyOne und StrategyTwo verwendet werden, um zu versuchen, durch den Raum zu gehen.

Kennzeichen

15
MStodd

Ich bin vielleicht falsch in meiner Meinung, aber ich behandle den Befehl als auszuführende Funktion oder Reaktion. Es sollten mindestens zwei Spieler vorhanden sein: derjenige, der die Aktion anfordert, und derjenige, der die Aktion ausführt. GUI ist ein typisches Beispiel für ein Befehlsmuster:

  • Alle Schaltflächen in der Anwendungssymbolleiste sind mit bestimmten Aktionen verbunden.
  • Button ist in diesem Fall der Executor.
  • Aktion ist in diesem Fall der Befehl.

Der Befehl ist normalerweise an einen bestimmten Bereich oder Geschäftsbereich gebunden, jedoch nicht erforderlich: Sie haben möglicherweise Befehle, die eine Rechnung ausstellen, eine Rakete starten oder eine Datei entfernen, die dieselbe Schnittstelle (z. B. eine einzelne execute()-Methode) innerhalb einer Anwendung implementiert. Befehle sind oft in sich geschlossen, so dass sie vom Executor nichts benötigen, um die Aufgabe auszuführen, die sie beabsichtigen (alle erforderlichen Informationen werden zur Konstruktionszeit angegeben). Manchmal sind Befehle kontextsensitiv und sollten diesen Kontext erkennen können (Der Befehl Backspace sollte die Einfügemarke im Text kennen, um das vorherige Zeichen korrekt zu entfernen. Der Befehl Rollback 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 definieren, um ein Datum zu formatieren (in UTC für das Gebietsschema spezifisch?) (Strategie für "Datumsformatierer") oder um ein Quadrat für eine geometrische Figur zu berechnen (Strategie für "Quadratrechner"). Strategien sind in diesem Sinne Fliegegewicht-Objekte, die etwas als Eingabe ("Datum", "Figur", ...) verwenden und auf deren Grundlage eine Entscheidung treffen. Vielleicht nicht das beste, aber ein gutes Beispiel für eine Strategie ist eine, die mit der javax.xml.transform.Source-Schnittstelle verbunden ist: Abhängig davon, ob das übergebene Objekt DOMSource oder SAXSource oder StreamSource ist, wendet die Strategie (in diesem Fall = XSLT-Transformer) andere Regeln für die Verarbeitung an. Die Implementierung kann eine einfache switch sein oder ein Verantwortungskettenmuster beinhalten.

Tatsächlich haben diese beiden Muster jedoch etwas gemeinsam: Befehle und Strategien kapseln Algorithmen innerhalb desselben semantischen Bereichs.

7
dma_k

Befehl:

Grundlegende Komponenten:

  1. Befehl deklariert eine Schnittstelle für abstrakte Befehle wie execute()
  2. Empfänger kann einen bestimmten Befehl ausführen
  3. Invoker enthält ConcreteCommand, das ausgeführt werden muss
  4. Client erstellt ConcreteCommand und weist Empfänger zu.
  5. ConcreteCommand definiert die Bindung zwischen Befehl und Empfänger

Arbeitsablauf:

Client ruft Invoker => Invoker ruft ConcreteCommand => ConcreteCommand ruft die Receiver - Methode auf, die die abstrakte Command - Methode implementiert.

Advantage: Der Client hat keine Auswirkungen auf Änderungen in Befehl und Empfänger. Der Invoker ermöglicht eine lose Kopplung zwischen Client und Empfänger. Sie können mehrere Befehle mit demselben Invoker ausführen.

BefehlMit dem Muster [ können Sie einen Befehl auf verschiedenen Empfänger ausführen, indem Sie dasselbe Invoker verwenden. Dem Invoker ist der Typ von Empfänger nicht bekannt.

Für ein besseres Verständnis der Begriffe, werfen Sie einen Blick auf diesen JournalDev article von Pankaj Kumar und dzone article von James Sugrue zusätzlich zu einem Wikipedia-Link.

Sie können Befehl -Muster für verwenden 

  1. Entkoppeln Sie den Aufrufer und Empfänger vom Befehl 

  2. Callback-Mechanismus implementieren

  3. Implementieren Sie die Rückgängig- und Wiederherstellungsfunktion

  4. Pflegen Sie eine Historie von Befehlen

Java.lang.Thread ist eine gute Implementierung von Command pattern. Sie können Thread als Aufrufer und Klasse behandeln, die lauffähig als ConcreteCommonad/Receiver und die run()-Methode als Befehl implementieren.

Die Undo/Redo-Version des Befehlsmusters kann unter Theodore Norvell'sarticle gelesen werden.

Strategie:

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 Tarifkomponente des Airline-Buchungssystems 

Fluggesellschaften möchten verschiedene Tarife zu unterschiedlichen Zeiten anbieten - Peak- und Off Peak-Monate. An Off-Peak-Reisetagen möchte sie die Nachfrage durch attraktive Rabatte anregen.

Wichtige Mitbringsel von Strategie:

  1. Es ist ein Verhaltensmuster
  2. Es basiert auf Delegation
  3. Es ändert die Eingeweide des Objekts, indem das Verhalten der Methode geändert wird
  4. Es wird verwendet, um zwischen den Algorithmen zu wechseln
  5. Es ändert das Verhalten des Objekts zur Laufzeit

Verwandte Beiträge mit Code-Beispielen:

Befehlsentwurfsmuster verwenden

Beispiel aus der realen Welt des Strategiemusters

4
Ravindra babu

Für mich ist der Unterschied eine Absicht. Die Implementierungen beider Muster sind ziemlich ähnlich, dienen jedoch unterschiedlichen Zwecken:

  • 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), es ist aber egal wie es tut.

  • Bei einem Befehl weiß die Komponente, die das Objekt verwendet, weder was der Befehl noch/ wie es - es weiß nur, wie es aufgerufen wird. Die Aufgabe des Aufrufers besteht nur darin, den Befehl auszuführen - die vom Befehl ausgeführte Verarbeitung ist nicht Bestandteil der Kernarbeit des Aufrufers.

Das ist der Unterschied - weiß oder kümmert das Objekt, das die Komponente verwendet, tatsächlich, was die Komponente tut? Meist kann dies dadurch bestimmt werden, ob das Musterobjekt einen Wert an seinen Aufrufer zurückgibt. Wenn sich der Aufrufer darum kümmert, was das Musterobjekt macht, wird er wahrscheinlich etwas zurückgeben wollen und es wird eine Strategie sein. Wenn es keinen Rückgabewert interessiert, handelt es sich wahrscheinlich um einen Befehl (Hinweis: So etwas wie ein Java Callable ist immer noch ein Befehl, da der Aufrufer zwar einen Wert zurückgibt, sich aber nicht um den Wert kümmert - er gibt ihn nur zurück was auch immer den Befehl geliefert hat).

0
BarrySW19