Java best practice: classe avec seulement des méthodes statiques

j'ai une application où j'ai une classe appelée PlausibilityChecker . Cette classe ne comporte que des méthodes statiques, comme checkZipcodeFormat ou checkMailFormat . Je les utilise dans mes classes GUI pour vérifier l'entrée avant de l'envoyer à la couche inférieure.

Est-ce une bonne pratique? J'ai pensé que j'utiliserais seulement des méthodes statiques pour ne pas avoir à me soucier de passer une instance aux classes GUI ou d'avoir un champ d'instance dans chaque classe gui qui ne fait pas référence à un objet gui.

j'ai remarqué que la classe Files de Java NIO n'a que des méthodes statiques donc je suppose que cela ne peut pas être si horriblement faux.

30
demandé sur N00b Pr0grammer 2015-07-14 17:47:47

6 réponses

je dirais que vous le faites bien. En dehors de cela, quelques conseils pour votre classe d'utilité:

  • assurez-vous qu'il n'y a pas d'état. C'est, il n'y a aucun champ dans la classe à moins qu'il ne soit déclaré static final . Aussi, assurez-vous que ce champ est immuable aussi bien par exemple String s.
  • assurez-vous qu'il ne peut pas être une super classe d'autres classes. Faites la classe final pour que les autres programmeurs ne puissent pas l'étendre.
  • Celui-ci est discutable, mais vous pouvez déclarer un constructeur no-arg private , de sorte qu'aucune autre classe ne pourrait créer une instance de votre classe utilitaire (en utilisant la réflexion ou quelque chose de similaire fera, mais il n'y a pas besoin d'aller cette protection avec la classe). Pourquoi vous ne pouvez pas faire cela? Eh bien, c'est le cas étrange où vous voulez/devez injecter une instance de la classe utility par exemple via une interface plutôt que de l'utiliser directement le long de votre classe. voici un exemple de ce . Cette conception est vraiment étrange mais peut se produire (comme montré dans le lien ci-dessus), mais si vous ne voulez pas courir dans un tel cas, le meilleur conseil est de garder le constructeur private .

il y a beaucoup de bibliothèques qui fournissent des classes d'utilité afin de nous aider programmeurs avec notre travail. L'une des plus connues est Apache Common ensemble de bibliothèques. Il est open source et vous pouvez vérifier le code pour voir comment ils conçoivent ces classes utilitaires pour créer le vôtre. (DISCLAIMER: je n'ai pas de travail ou de soutenir ces bibliothèques, je suis un heureux utilisateur)

Note importante: éviter d'utiliser un singleton pour votre classe d'utilité .

29
répondu Luiggi Mendoza 2017-05-23 12:10:11

en Java 8, Vous pouvez maintenant changer vos classes d'Utilités statiques en interfaces avec des implémentations statiques. Cela élimine la nécessité de rendre la classe finale et d'avoir à fournir un constructeur privé. C'est aussi simple que de changer "classe" en "interface" et de supprimer le mot final si vous l'avez (toutes les interfaces sont abstraites donc elles ne peuvent pas être finales). Comme les méthodes d'interface sont toujours publiques, vous pouvez en supprimer toute portée publique. Si vous avez un constructeur privé puis Supprimer que de même (vous ne pouvez pas compiler une interface avec un constructeur puisqu'elle ne peut pas être instanciée). C'est moins de code et semble plus propre. Vous n'aurez pas à refactoriser toutes les classes qui l'utilisent déjà.

9
répondu afenkner 2016-09-14 13:16:18

ne vous inquiétez pas de subclassing ou instantiation. Les classes d'utilité suivantes de JDK peuvent être sous-classées ou instanciées, mais personne ne les a utilisées de manière abusive au cours de toutes ces années. Les gens ne sont pas que stupide.

java.beans.Beans
java.beans.PropertyEditorManager
java.lang.invoke.LambdaMetafactory
java.lang.reflect.Modifier
java.net.URLDecoder                                   ...but not URLEncoder:)
javax.management.DefaultLoaderRepository
javax.management.Query
javax.management.loading.DefaultLoaderRepository
javax.management.relation.RoleStatus
javax.print.ServiceUI
javax.swing.UIManager
javax.swing.plaf.basic.BasicBorders
javax.swing.plaf.basic.BasicGraphicsUtils
javax.swing.plaf.basic.BasicHTML
javax.swing.plaf.basic.BasicIconFactory
javax.swing.plaf.metal.MetalBorders
javax.swing.plaf.metal.MetalIconFactory
javax.swing.text.Utilities
javax.swing.text.html.HTML

Cependant, en tant qu'API publique, vous voulez supprimer le constructeur par défaut, sinon il y a un constructeur non documenté sur la page javadoc qui est maladroit et déroutant. Pour vos propres API internes, ça n'a pas d'importance, personne ne se soucie.

il n'y a aucune raison de supprimer le sous-classement. Si quelqu'un veut classer un cours d'utilité, pour une raison quelconque, qu'il le fasse. Bien sûr, le constructeur privé supprimera le sous-classement comme un effet secondaire.


Dans java8, il y a plus de possibilités de conception à prendre en considération -

une interface avec toutes les méthodes statiques - c'est aussi bon qu'une classe avec toutes les méthodes statiques méthode. Ni l'interface ni la classe ne sont conçues pour cela, donc l'une ou l'autre est OK. Cependant, ne vous attendez pas à hériter de ces méthodes statiques dans les sous - types de l'interface-les méthodes statiques d'interface ne sont pas héritables. Un point positif pour l'utilisation de l'interface est que nous n'avons pas besoin de supprimer le constructeur par défaut d'apparaître sur javadoc.

Une interface avec toutes les méthodes par défaut , accessible par l'héritage. Ce qui est intéressant, mais un problème d' en général (l'héritage ne fonctionne que dans un contexte non statique). Mais cela pourrait être une meilleure option dans certaines conceptions D'API, par exemple, cette API HTML builder .

4
répondu ZhongYu 2015-07-14 16:16:50

pourquoi ne devrait-il pas être une bonne pratique si vous avez simplement des méthodes qui fournissent des "outils" à d'autres classes, c'est très bien.

1
répondu Mirko 2015-07-14 14:50:50

Singleton sont ok, en fonction du contexte.

à des fins d'essai, vous pouvez supprimer les références à Singleton afin d'éviter les effets secondaires pendant les essais unitaires. Dans ce cas, il est probablement logique d'utiliser un framework d'injection de dépendances tel que Spring pour gérer la création de l'instance et d'utiliser des méthodes régulières qui peuvent être dépassées au lieu de méthodes statiques.

si vous prévoyez toujours d'utiliser des méthodes statiques, assurez-vous que les appels sont thread-safe s'ils sont utilisés dans un contexte multi-threaded. (par exemple double verrouillage vérifié).

1
répondu Jin Kim 2015-07-14 14:55:13

Classes avec seulement des méthodes statiques est un modèle commun en Java pour les méthodes d'utilité. Exemples dans la bibliothèque standard comprennent Fichiers , Collections , et Exécuteurs .

pour de telles classes d'utilité, c'est une bonne idée de s'assurer que votre classe ne peut pas être instanciée, pour rendre l'intention de la classe claire. Vous pouvez le faire en déclarant explicitement un constructeur privé. Voir Point 4: Pour plus de détails, veuillez contacter un constructeur privé dans "Java efficace" par Josh Bloch.

1
répondu markusk 2015-07-14 14:58:10