Le modèle de conception de la stratégie est souvent considéré comme un substitut aux fonctions de première classe dans les langues qui en manquent.
Par exemple, disons que vous vouliez transmettre des fonctionnalités à un objet. En Java, vous devez passer dans l'objet un autre objet qui encapsule le comportement souhaité. Dans un langage tel que Ruby, vous passeriez simplement la fonctionnalité elle-même sous la forme d'une fonction anonyme.
Cependant, j'y pensais et j'ai décidé que la stratégie offrait peut-être plus qu'une simple fonction anonyme.
En effet, un objet peut contenir un état qui existe indépendamment de la période d'exécution de sa méthode. Cependant, une fonction anonyme en elle-même ne peut conserver qu'un état qui cesse d'exister au moment où la fonction termine son exécution.
Dans un langage orienté objet qui prend en charge les fonctions de première classe, le modèle de stratégie a-t-il un avantage sur l'utilisation des fonctions?
la source
Réponses:
Lorsque le langage prend en charge les références à la fonction ( Java le fait depuis la version 8 ), celles-ci sont souvent une bonne alternative pour les stratégies, car elles expriment généralement la même chose avec moins de syntaxe. Cependant, il existe certains cas où un objet réel peut être utile.
Une interface de stratégie peut avoir plusieurs méthodes. Prenons une interface
RouteFindingStragegy
comme exemple, qui encapsule différents algorithmes de recherche d'itinéraire. Il pourrait déclarer des méthodes commeRoute findShortestRoute(Node start, Node destination)
boolean doesRouteExist(Node start, Node destination)
Route[] findAllPossibleRoutes(Node start, Node destination)
Route findShortestRouteToClosestDestination(Node start, Node[] destinations)
Route findTravelingSalesmanRoute(Node[] stations)
qui seraient alors tous mis en œuvre par la stratégie. Certains algorithmes de recherche d'itinéraire peuvent permettre des optimisations internes pour certains de ces cas d'utilisation et d'autres non, de sorte que l'implémenteur peut décider comment implémenter chacune de ces méthodes.
Un autre cas est celui où la stratégie a un état intérieur. Bien sûr, dans certaines langues, les fermetures peuvent avoir un état intérieur, mais lorsque cet état intérieur devient très complexe, il devient souvent plus élégant de promouvoir la fermeture à une classe à part entière.
la source
Il n'est pas vrai qu'une fonction anonyme ne peut conserver l'état qui cesse d'exister lorsque la fonction termine son exécution.
Prenons l'exemple suivant en Common Lisp:
Cette fonction prend une liste de chaînes et ajoute un compteur à chaque élément de la liste. Ainsi, par exemple, en invoquant
donne
La fonction
number-strings
utilise en interne une fonction anonyme avec une variablecounter
qui contient l'état (la valeur actuelle du compteur) qui est réutilisée chaque fois que la fonction est invoquée.En général, vous pouvez considérer une fermeture comme un objet avec une seule méthode. Alternativement, un objet est une collection de fermetures qui partagent les mêmes variables fermées. Je ne sais donc pas s'il existe des cas dans lesquels vous devez utiliser un objet au lieu d'une fermeture: je dirais que les deux sont des façons de regarder le même modèle sous des perspectives différentes.
En particulier, le modèle de stratégie nécessite un objet avec une seule méthode, donc une fermeture devrait faire le travail. Mais, comme Philipp l'a observé dans sa réponse, selon les circonstances (état complexe) et les langages de programmation, vous pouvez obtenir une solution plus élégante en utilisant des objets.
la source
let
puis définir ma fermeture à l'intérieur. En gros, j'aurais défini un objet avec une méthode à la volée. Dans un autre langage (par exemple Java), il pourrait être plus pratique (syntaxiquement plus simple) de définir un objet approprié pour conserver l'état. Donc, je déciderais au cas par cas.Ce n'est pas parce que deux conceptions peuvent résoudre le même problème qu'elles sont des substitutions directes l'une de l'autre.
Si vous devez suivre l'état dans un programme fonctionnel, vous ne modifiez pas une variable fermée, même si le langage le permet. Vous organisez pour appeler une fonction qui prend un état comme argument et renvoie le nouvel état comme valeur de retour.
Votre architecture sera très différente, mais vous atteindrez le même objectif. N'essayez pas de forcer les modèles d'un paradigme directement sur l'autre.
la source
La stratégie est un concept , une recette utile pour résoudre un problème particulier et récurrent. Ce n'est pas une construction de langage, ni une quelconque forme d' implémentation . Une clôture peut être utilisée pour mettre en œuvre la stratégie un jour et Observer le lendemain.
Le terme stratégie est surtout utile dans les conversations avec d'autres programmeurs pour exprimer de manière concise votre intention. Il n'y a rien de magique là-dedans.
la source