Désolée, je ne trouve pas de question répondant à cela, je suis presque certain que quelqu'un d'autre l'a déjà posée.
Mon problème est que j'écris des bibliothèques système pour exécuter des périphériques embarqués. J'ai des commandes qui peuvent être envoyées à ces appareils via des émissions radio. Cela ne peut être fait que par texte. dans les bibliothèques système, j'ai un thread qui gère les commandes qui ressemblent à ceci
if (value.equals("A")) { doCommandA() }
else if (value.equals("B")) { doCommandB() }
else if etc.
Le problème est qu'il y a beaucoup de commandes qui vont rapidement dégénérer en quelque chose hors de contrôle. Horrible à surveiller, pénible à déboguer et époustouflant à comprendre dans quelques mois.
Réponses:
en utilisant le modèle de commande :
puis construisez un
Map<String,Command>
objet et remplissez-le avec desCommand
instances:alors vous pouvez remplacer votre chaîne if / else if par:
ÉDITER
vous pouvez également ajouter des commandes spéciales telles que
UnknownCommand
ouNullCommand
, mais vous avez besoin d'unCommandMap
qui gère ces cas d'angle afin de minimiser les vérifications du client.la source
Ma suggestion serait une sorte de combinaison légère d'énumération et d'objet Command. C'est un idiome recommandé par Joshua Bloch dans l'article 30 de Effective Java.
Bien sûr, vous pouvez passer des paramètres à doCommand ou avoir des types de retour.
Cette solution peut ne pas vraiment convenir si les implémentations de doCommand ne «correspondent» pas vraiment au type enum, ce qui est - comme d'habitude lorsque vous devez faire un compromis - un peu flou.
la source
Avoir une énumération de commandes:
Si vous avez plus de quelques commandes, envisagez d'utiliser le modèle de commande, comme indiqué ailleurs (bien que vous puissiez conserver l'énumération et incorporer l'appel à la classe d'implémentation dans l'énumération, au lieu d'utiliser un HashMap). Veuillez consulter la réponse d'Andreas ou de jens à cette question pour un exemple.
la source
Implémenter une interface comme démontré simplement et clairement par dfa est propre et élégant (et de manière "officiellement" prise en charge). C'est à cela que sert le concept d'interface.
En C #, nous pourrions utiliser des délégués pour les programmeurs qui aiment utiliser des pointeurs de fonction en c, mais la technique de DFA est la manière d'utiliser.
Vous pourriez aussi avoir un tableau
Ensuite, vous pouvez exécuter une commande par index
Plagier à partir de DFA, mais ayant une classe de base abstraite au lieu d'une interface. Notez la cmdKey qui sera utilisée plus tard. Par expérience, je me rends compte que souvent une commande d'équipement a aussi des sous-commandes.
Construisez vos commandes ainsi,
Vous pouvez ensuite étendre HashMap ou HashTable générique en fournissant une fonction de succion de paire clé-valeur:
Ensuite, construisez votre magasin de commandes:
Maintenant, vous pouvez envoyer des contrôles objectivement
la source
Eh bien, je suggère de créer des objets de commande et de les mettre dans un hashmap en utilisant la chaîne comme clé.
la source
Même si je pense que l'approche du modèle de commande est plus orientée vers les meilleures pratiques et maintenable à long terme, voici une option unique pour vous:
org.apache.commons.beanutils.MethodUtils.invokeMethod (this, "doCommand" + value, null);
la source
J'essaye généralement de le résoudre de cette façon:
cela présente de nombreux avantages:
1) il n'est pas possible d'ajouter une énumération sans implémenter exec. pour ne pas manquer un A.
2) vous n'aurez même pas à l'ajouter à une carte de commande, donc pas de code standard pour la construction de la carte. juste la méthode abstraite et ses implémentations. (qui est sans doute aussi passe-partout, mais il ne sera pas plus court ..)
3) vous économiserez tous les cycles de processeur perdus en parcourant une longue liste de if ou en calculant les hashCodes et en effectuant des recherches.
edit: si vous n'avez pas d'énumérations mais des chaînes comme source, utilisez simplement
Command.valueOf(mystr).exec()
pour appeler la méthode exec. notez que vous devez utiliser le modificateur public sur exec si vous souhaitez l'appeler à partir d'un autre package.la source
Il vaut probablement mieux utiliser une carte de commandes.
Mais si vous avez un ensemble de ces éléments à gérer, vous vous retrouvez avec des tonnes de cartes qui frappent. Ensuite, cela vaut la peine de le faire avec Enums.
Vous pouvez le faire avec un Enum sans utiliser de commutateurs (vous n'avez probablement pas besoin des getters dans l'exemple), si vous ajoutez une méthode à Enum pour résoudre la "valeur". Ensuite, vous pouvez simplement faire:
Mise à jour: ajout d'une carte statique pour éviter l'itération à chaque appel. Sans vergogne pincé de cette réponse .
la source
La réponse fournie par @dfa est la meilleure solution, à mon avis.
Je fournis juste quelques extraits au cas où vous utiliseriez Java 8 et voudriez utiliser Lambdas!
Commande sans paramètres:
(vous pouvez utiliser un Runnable au lieu de Command, mais je ne le considère pas comme sémantiquement correct):
Commande avec un paramètre:
Au cas où vous attendez un paramètre que vous pourriez utiliser
java.util.function.Consumer
:Dans l'exemple ci-dessus,
doSomethingX
est une méthode présente dansmyObj
la classe de qui prend n'importe quel objet (nomméparam
dans cet exemple) comme argument.la source
si vous avez plusieurs instructions imbriquées 'if', il s'agit d'un modèle pour l'utilisation d'un moteur de règles . Voir, par exemple, JBOSS Drools .
la source
Utilisez simplement un HashMap, comme décrit ici:
la source
s'il était possible d'avoir un tableau de procédures (ce que vous avez appelé des commandes) qui seraient utiles ..
mais vous pouvez écrire un programme pour écrire votre code. Tout est très systématique if (value = 'A') commandA (); sinon si (........................ etc
la source
Je ne sais pas si vous avez un chevauchement entre le comportement de vos différentes commandes, mais vous voudrez peut-être également jeter un coup d'œil au modèle Chain Of Responsibility qui pourrait offrir plus de flexibilité en permettant à plusieurs commandes de gérer certaines valeurs d'entrée.
la source
Le modèle de commande est la voie à suivre. Voici un exemple utilisant java 8:
1. Définissez l'interface:
2. Implémentez l'interface avec chacune des extensions:
et
etc .....
3. Définissez le client:
4. Et voici le résultat de l'exemple:
la source
S'il fait beaucoup de choses, alors il y aura beaucoup de code, vous ne pouvez pas vraiment vous en éloigner. Simplifiez-vous le suivi, donnez aux variables des noms très significatifs, les commentaires peuvent aussi aider ...
la source