Modèle de conception de stratégie modifiée

11

J'ai commencé à étudier les modèles de conception récemment, et une chose que je code conviendrait parfaitement au modèle de stratégie, à l'exception d'une petite différence.

Essentiellement, certains (mais pas tous) de mes algorithmes ont besoin d'un ou deux paramètres supplémentaires qui leur sont transmis.

Je vais donc devoir

  • leur passer un paramètre supplémentaire lorsque j'invoque leur méthode de calcul

ou

  • les stocker en tant que variables dans la classe ConcreteAlgorithm, et pouvoir les mettre à jour avant d'appeler l'algorithme.

Existe-t-il un modèle de conception pour ce besoin / Comment pourrais-je l'implémenter tout en respectant le modèle de stratégie?

J'ai envisagé de passer l'objet client à tous les algorithmes et d'y stocker les variables, puis de ne l'utiliser que lorsque l'algorithme en a besoin. Cependant, je pense que cela est à la fois difficile à manier et va à l'encontre du point du modèle de stratégie.

Juste pour être clair, je l'implémente en Java, et donc je n'ai pas le luxe de paramètres facultatifs (ce qui résoudrait bien cela).

Megan Walker
la source
Les paramètres facultatifs comme en C ++ ne résoudraient rien, car ils ne sont qu'un raccourci pour définir plusieurs méthodes surchargées.
maaartinus
Je ferais de mon mieux pour éviter de stocker les paramètres supplémentaires quelque part où je devais les changer avant utilisation. De cette façon, vous rendez ConcreteAlgorithm avec état, il ne peut donc pas être transmis facilement à d'autres méthodes ou threads. De plus, il est trop facile d'oublier de régler les paramètres.
maaartinus

Réponses:

5

Samuel, est-il possible d'encapsuler le paramètre que chacune des stratégies prend dans une classe commune, puis d'étendre cette classe de paramètre commune pour ajouter plus de comportement dont certaines de vos stratégies ont spécifiquement besoin?

Par exemple

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

Et puis, définissez une hiérarchie de stratégie comme:

Interface MyStrategy {
   void myStrategyMethod(StrategyParameter parameter);
}

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

appeler la stratégie ci-dessus comme: myNormalStrategyInstance.myStrategyMethod(strategyParameter);

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

appeler la stratégie ci-dessus en passant l' SpecialStrategyParameterinstance à la place comme:mySpecializedStrategy.myStrategyMethod(specialStrategyParameter);

Veuillez mettre à jour si quelque chose n'est pas clair. Sera heureux d'expliquer / clarifier.

Peakit
la source
2
-1 nécessite un abaissement, rompt l'encapsulation de la conception. Bien qu'il s'agisse d'une amélioration de la conception de la question, il existe de meilleures façons d'écorcher ce chat.
tallseth
@tallseth je vois aussi abattu. Mais je ne vois pas de meilleures façons. Pourriez-vous s'il vous plaît indiquer une meilleure solution? Un article ou quelque chose?
Narek
En fait, oui. @ Jordão a la réponse que je préférerais, sur la base des détails que nous avons dans la question. Cette réponse joue sur les forces du modèle de stratégie. Si nous suivions l'approche dans cette réponse, j'aurais voulu StrategyParametercontenir tous les paramètres possibles, tout comme un DTO. Certaines mises en œuvre de la stratégie pourraient les ignorer. Dans certains cas, c'est la meilleure approche. Le contexte est roi pour ce genre de problèmes.
tallseth
4

Vous devez clarifier votre stratégie .

Tout dépend de la façon dont vous utilisez vos algorithmes. Pour que votre classe client utilise différentes implémentations de stratégies de manière interchangeable, elles doivent toutes avoir une abstraction commune . S'ils ne suivent pas la même interface, vous avez peut-être besoin de différentes abstractions .

J'ai déjà utilisé des stratégies configurables , où vous paramétrez les classes concrètes sur la construction:

interface Strategy {
  int calculate();
}

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

Maintenant, quelqu'un doit encore créer une instance de cette classe et la transmettre à votre client. Mais votre client n'a toujours besoin que de connaître l' Strategyinterface.

Cela fonctionne également si votre méthode de stratégie prend des paramètres, mais votre client connaît ces paramètres et les transmet à toutes les implémentations avec lesquelles il travaille.

Jordão
la source
Le client est celui qui a le contexte pour fournir le paramètre.
andyczerwonka
1

Tant que la signature est clairement définie sur l'interface, elle est toujours conforme au modèle de stratégie.

Les modèles tels qu'ils sont écrits sont la forme la plus simple absolue qui présente toujours le comportement attendu, vous pouvez donc les embellir tant que vous conservez l'intention d'origine. Cela suppose bien sûr que vous vouliez suivre le modèle. Cela ne sert à rien d'utiliser un motif s'il ne convient pas, ou simplement parce qu'il est là, mais dans votre cas, je pense que vous allez bien.

Ian
la source
0

étendant la réponse ci-dessus fournie par peakit - vous pouvez utiliser l'abstraction. J'utilise le code de Peakit ici -

Interface MyStrategy { résumé void myStrategyMethod (paramètre StrategyParameter); }

La classe MyNormalStrategy étend MyStrategy {remplacement public void myStrategyMethod (paramètre StrategyParameter) {// implémentez la logique ici}}

La classe MySpecializedStrategy étend MyStrategy {remplacement public void myStrategyMethod (paramètre StrategyParameter, ExtraStrategyParameter extraParameter) {// implémentez la logique ici} }

Si je comprends bien votre question, vous vouliez passer un paramètre supplémentaire à certains algorithmes, n'est-ce pas? Veuillez me faire savoir si c'est ce que vous cherchiez?


la source
0

Si vous regardez dans le livre des modèles de conception, il n'est pas faux en soi qu'il existe une SimpleStrategy qui utilise moins ou aucun des paramètres passés, ou que les paramètres sont un multiplicateur à taille unique / le moins commun. Le choix de conception ici est de savoir si cela vous fait mal en termes de traitement supplémentaire qui finit par ne pas être utilisé.

pjv
la source