Modifiziertes Strategie-Entwurfsmuster

11

Ich habe vor kurzem angefangen, mich mit Designmustern zu befassen, und eine Sache, die ich codiere, würde perfekt zum Strategiemuster passen, abgesehen von einem kleinen Unterschied.

Im Wesentlichen benötigen einige (aber nicht alle) meiner Algorithmen einen oder zwei zusätzliche Parameter, die an sie übergeben werden.

Also muss ich entweder

  • Übergeben Sie ihnen einen zusätzlichen Parameter, wenn ich ihre Berechnungsmethode aufrufe

oder

  • Speichern Sie sie als Variablen in der ConcreteAlgorithm-Klasse und können Sie sie aktualisieren, bevor ich den Algorithmus aufrufe.

Gibt es ein Entwurfsmuster für diesen Bedarf / Wie kann ich dies implementieren, während ich mich an das Strategiemuster halte?

Ich habe überlegt, das Client-Objekt an alle Algorithmen zu übergeben, die Variablen dort zu speichern und es dann nur dann zu verwenden, wenn der jeweilige Algorithmus es benötigt. Ich denke jedoch, dass dies sowohl unhandlich ist als auch den Punkt des Strategiemusters zunichte macht.

Um ganz klar zu sein, ich implementiere in Java und habe daher nicht den Luxus optionaler Parameter (was dies gut lösen würde).

Megan Walker
quelle
Optionale Parameter wie in C ++ würden nichts lösen, da sie nur eine Abkürzung für die Definition mehrerer überladener Methoden sind.
Maaartinus
Ich würde mich bemühen, die zusätzlichen Parameter nicht an einem Ort zu speichern, an dem ich sie vor der Verwendung ändern musste. Auf diese Weise machen Sie ConcreteAlgorithm statusbehaftet, sodass es nicht einfach an andere Methoden oder Threads übergeben werden kann. Außerdem ist es zu leicht zu vergessen, die Parameter einzustellen.
Maaartinus

Antworten:

5

Samuel, ist es möglich, den Parameter, den jede der Strategien annimmt, in eine gemeinsame Klasse zu kapseln und diese gemeinsame Parameterklasse dann zu erweitern, um mehr Verhalten hinzuzufügen, das einige Ihrer Strategien speziell benötigen?

Z.B

StrategyParameter //Base strategy parameter that most of the strategies need
        ^
        |
        |
SpecialStrategyParameter // will be used for strategies that need more parameter

Definieren Sie dann die Strategiehierarchie wie folgt:

Interface MyStrategy {
   void myStrategyMethod(StrategyParameter parameter);
}

class MyNormalStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

Nennen Sie die obige Strategie wie folgt: myNormalStrategyInstance.myStrategyMethod(strategyParameter);

class MySpecializedStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

Rufen Sie die obige Strategie auf, indem Sie SpecialStrategyParameterstattdessen die Instanz wie folgt übergeben:mySpecializedStrategy.myStrategyMethod(specialStrategyParameter);

Bitte aktualisieren Sie, wenn etwas nicht klar ist. Wird gerne erklären / klären.

Peakit
quelle
1
-1 erfordert Downcast, unterbricht die Kapselung des Designs. Obwohl es eine Verbesserung des Designs in der Frage ist, gibt es bessere Möglichkeiten, diese Katze zu häuten.
Tallseth
@ Tallseth Ich sehe auch niedergeschlagen. Aber ich sehe keine besseren Wege. Könnten Sie bitte auf eine bessere Lösung hinweisen? Ein Artikel oder so?
Narek
Eigentlich ja. @ Jordão hat die Antwort, die ich bevorzugen würde, basierend auf den Details, die wir in der Frage haben. Diese Antwort spielt mit den Stärken des Strategiemusters. Wenn wir den Ansatz in dieser Antwort gewählt hätten, hätte ich gerne StrategyParameteralle möglichen Parameter, nur als DTO. Einige Implementierungen der Strategie könnten sie ignorieren. In einigen Fällen ist dies der beste Ansatz. Der Kontext ist König für diese Art von Themen.
Tallseth
3

Sie müssen Ihre Strategie klarstellen .

Es hängt alles davon ab , wie Sie verwenden Ihre Algorithmen. Damit Ihre Client-Klasse verschiedene Strategieimplementierungen austauschbar verwenden kann, müssen alle eine gemeinsame Abstraktion haben . Wenn sie nicht der gleichen Oberfläche folgen, benötigen Sie möglicherweise unterschiedliche Abstraktionen .

Ich habe zuvor konfigurierbare Strategien verwendet, bei denen Sie die konkreten Klassen für die Konstruktion parametrisieren:

interface Strategy {
  int calculate();
}

class ConcreteStrategyThatNeedsAParameter implements Strategy {
  private final int param;
  public ConcreteStrategyThatNeedsAParameter(int param) {
    this.param = param;
  }
  public int calculate() { 
    // uses param...
  }
}

Jetzt muss noch jemand eine Instanz dieser Klasse erstellen und an Ihren Client übergeben. Ihr Client muss jedoch nur noch über die StrategyBenutzeroberfläche Bescheid wissen .

Es funktioniert auch , wenn Sie Ihre Strategie Methode Parameter übernimmt, aber dann Ihr Kunde weiß über diese Parameter und übergibt sie an allen Implementierungen es funktioniert mit.

Jordão
quelle
Der Client ist derjenige mit dem Kontext, der den Parameter bereitstellt.
andyczerwonka
1

Solange die Signatur auf der Benutzeroberfläche klar definiert ist, entspricht sie weiterhin dem Strategiemuster.

Die geschriebenen Muster sind die absolut einfachste Form, die immer noch das erwartete Verhalten aufweist, sodass Sie sie verschönern können, solange Sie die ursprüngliche Absicht beibehalten. Das setzt natürlich voraus, dass Sie dem Muster folgen möchten. Es macht keinen Sinn, ein Muster zu verwenden, wenn es nicht passt oder nur weil es da ist, aber in Ihrem Fall denke ich, dass es Ihnen gut geht.

Ian
quelle
0

Erweitern Sie die obige Antwort von peakit - Sie können die Abstraktion verwenden. Ich verwende hier den Peakit-Code -

Schnittstelle MyStrategy { abstract void myStrategyMethod (Parameter StrategyParameter); }}

Klasse MyNormalStrategy erweitert MyStrategy {public override void myStrategyMethod (Parameter StrategyParameter) {// Logik hier implementieren}}

Klasse MySpecializedStrategy erweitert MyStrategy {public override void myStrategyMethod (Parameter StrategyParameter, ExtraStrategyParameter extraParameter) {// Logik hier implementieren} }

Wenn ich Ihre Frage richtig verstehe, wollten Sie bestimmten Algorithmen einen zusätzlichen Parameter übergeben, oder? Bitte lassen Sie mich wissen, ob dies das ist, wonach Sie gesucht haben.


quelle
0

Wenn Sie sich das Buch mit den Entwurfsmustern ansehen, ist es an sich nicht falsch, dass eine SimpleStrategy existiert, die weniger oder keinen der übergebenen Parameter verwendet, oder dass die Parameter ein Einheitsgrößen- / Kleinst-Multiplikator sind. Die Wahl des Designs hier ist, ob dies Sie in Bezug auf zusätzliche Verarbeitung verletzt, die letztendlich nicht verwendet wird.

pjv
quelle