Les classes auxiliaires / utilitaires doivent-elles être abstraites?

Je me trouve souvent à extraire des comportements courants de classes dans des classes utilitaires / utilitaires qui ne contiennent rien d’autre qu’un ensemble de méthodes statiques. Je me suis souvent demandé si je devais déclarer ces classes comme abstraites, car je ne peux pas vraiment penser à une raison valable de les instancier.

Qu’est-ce que les avantages et les inconvénients seraient de déclarer une telle classe comme abstraite.

public [abstract] class Utilities{ public static Ssortingng getSomeData(){ return "someData"; } public static void doSomethingToObject(Object arg0){ } } 

Vous pouvez simplement déclarer un constructeur privé qui ne fait rien.

Le problème avec la déclaration de la classe “abstract” est que le mot-clé abstract signifie généralement que la classe est destinée à être sous-classée et étendue. Ce n’est certainement pas ce que vous voulez ici.

Ne vous embêtez pas à les rendre abstraits, mais incluez un constructeur privé sans paramètre pour empêcher leur instanciation.

Point de comparaison pour les personnes intéressées: en C #, vous déclareriez la classe statique, la rendant abstraite et scellée (Java final) sous la forme compilée, et sans aucun constructeur d’instance. Cela en fait également une erreur de compilation pour déclarer un paramètre, une variable, un tableau, etc. de ce type. Pratique.

Je ne déclare pas les classes d’utilité abstraites, je les déclare finales et rend le constructeur privé. De cette façon, ils ne peuvent pas être sous-classés et ils ne peuvent pas être instanciés.

 public final class Utility { private Utility(){} public static void doSomethingUseful() { ... } } 

En les déclarant abstraits, vous indiquez en fait aux autres codeurs dont vous avez prévu que ces classes soient dérivées. Vraiment, vous avez raison, il n’y a pas beaucoup de différence, mais la sémantique ici est bien plus sur l’interprétation d’autres personnes qui regardent votre code.

J’appendais plus de pas au-delà du constructeur privé:

 public class Foo { // non-instantiable class private Foo() { throw new AssertionError(); } } 

Lancer l’ AssertionError empêche les méthodes de la même classe d’instancier la classe (enfin, elles peuvent essayer). Ce n’est normalement pas un problème, mais dans un environnement d’équipe, on ne sait jamais ce que quelqu’un va faire.

En ce qui concerne le mot-clé “abstract”, j’ai remarqué des classes d’utilitaires sous-classées dans de nombreux cas:

 public class CoreUtils { ... } public class WebUtils extends CoreUtils { ... } public class Foo { ... WebUtils.someMethodInCoreUtils() ... } 

Je crois que cela est fait pour que les gens n’aient pas à se souvenir de la classe d’utilitaire à inclure. Y a-t-il des inconvénients à cela? Est-ce un anti-pattern?

Cordialement, LES

Comme d’autres l’ont déclaré, créez un constructeur sans paramètre privé. Personne ne peut en créer une instance, à part la classe elle-même.

Comme d’autres l’ont montré avec d’autres langages, voici comment procéder dans la prochaine version de C ++, comment rendre une classe non instanciable:

 struct Utility { static void doSomething() { /* ... */ } Utility() = delete; }; 

Non, mais si votre langage le supporte, il y a un argument fort pour dire que dans la plupart des cas, ils doivent (peuvent) être déclarés comme “statiques” … Statique indique au compilateur qu’ils ne peuvent pas être instanciés et que toutes les méthodes qu’ils contiennent doit être statique.

Abstract est pour les classes qui ont des détails d’implémentation basés sur l’instance, qui seront utilisés par les instances des classes dérivées …

Quelqu’un a mentionné que dans C # 3.0, vous pouviez accomplir cela via des méthodes d’extension. Je ne suis pas un gars de C #, je l’ai fait en 1,5 / 2,0 jours, mais je ne l’ai pas utilisé depuis. Basé sur une compréhension très sommaire, je pense que quelque chose de similaire peut être accompli en Java avec des importations statiques. Je me rends compte que ce n’est pas du tout la même chose, mais si le but est simplement de rendre ces méthodes utilitaires un peu plus “natives” (faute d’un meilleur terme) pour la classe appelante, je pense que cela fera l’affaire. En supposant la classe d’utilitaires que j’ai déclarée dans ma question initiale.

 import static Utilities.getSomeData; public class Consumer { public void doSomething(){ Ssortingng data = getSomeData(); } } 

Puis-je offrir des conseils constructifs?

Si vous faites beaucoup de choses, vous rencontrerez deux problèmes.

Tout d’abord, une méthode statique prenant un paramètre doit souvent faire partie de l’object correspondant à ce paramètre. Je me rends compte que cela n’aide pas pour des objects comme Ssortingng, mais s’il prend des objects que vous avez définis, vous pourriez certainement améliorer l’object en incluant votre assistant comme méthode de cet object.

Si elle prend toutes les valeurs natives, vous pourriez probablement définir un object dont il s’agit. Vérifiez si vous pouvez trouver un regroupement de ces valeurs natives et regroupez-les en tant qu’object. Si vous essayez juste cela, vous trouverez beaucoup d’autres utilisations pour ce petit mini-object, et avant que vous le sachiez, ce sera incroyablement utile.

Une autre chose, si vous avez une classe utilitaire avec un tas de méthodes statiques semi-liées et de variables statiques, vous voudrez presque toujours qu’il s’agisse d’un singleton. J’ai découvert cela par essais et erreurs, mais lorsque vous découvrez que vous avez besoin de plus d’un (il y en aura), il est BEAUCOUP plus facile de faire un singleton dans un multipleton (?) Puis d’essayer de convertir une classe statique en un multiplet ( ok, donc je fais des mots maintenant).

Bonne chance. Ce truc était pour la plupart un essai et une erreur pour moi, mais il y a 5 ans, et je n’ai jamais trouvé un exemple où je regrettais de ne pas avoir de classe / méthodes statiques.

Les méthodes d’assistance / utilitaire conviennent parfaitement. Ne vous souciez pas de les append à une bibliothèque dans votre application ou votre framework. La plupart des frameworks que j’ai vus les utilisent dans de nombreuses variétés.

Cela étant dit, si vous voulez être très astucieux à leur sujet, vous devriez examiner les méthodes d’extension en C # 3.0. L’utilisation de la méthode d’extension rendra vos utilitaires un peu plus «holistique» dans votre cadre, ce qui semble être ce que vous essayez de faire en les rendant abstraits. Sans parler de la méthode d’extension, c’est très amusant d’écrire!