Historique de la question
Depuis le début, Java a été conçu comme un langage orienté objet, où le principal objectif était de créer des instances de classes. Cependant, pour les méthodes souvent utilisées (par exemple, le tri, la transformation de données), des classes utilitaires avec un ensemble de méthodes statiques (par exemple, java.util.Collections) ont commencé à apparaître.
Problème
Les méthodes statiques simplifient l'appel des fonctions d'assistance, mais ne conviennent pas au stockage d'état, à l'injection de dépendances et aux tests en isolation. D'autre part, les instances de classes sont plus flexibles, mais augmentent la quantité de code pour l'initialisation et nécessitent un cycle de vie bien réfléchi.
Solutions
Classes utilitaires (utility classes) — ensemble de méthodes statiques sans état, ne nécessitant pas la création d'un objet. Bonnes pour les manipulations sur des collections, des transformations, des opérations mathématiques.
Instances de classes — stockent l'état, utilisent des dépendances, assurent extensibilité et testabilité. Utilisées dans la logique métier, les services, les contrôleurs, etc.
Exemple de code :
// Exemple de classe utilitaire public class MathUtils { public static int add(int a, int b) { return a + b; } } // Utilisation : int sum = MathUtils.add(1, 2); // Exemple d'instance de classe pour la logique métier public class OrderService { private final OrderRepository repo; public OrderService(OrderRepository repo) { this.repo = repo; } public void placeOrder(Order o) { repo.save(o); } }
Caractéristiques clés :
Peut-on hériter des classes utilitaires et étendre leurs méthodes statiques ?
Non, en général, les classes utilitaires sont déclarées final, avec un constructeur privé. L'héritage des méthodes statiques est possible, mais n'a pas de sens, car les méthodes statiques ne sont pas héritées au niveau de l'appel d'instance.
Exemple de code :
public final class MyUtils { private MyUtils() {} // empêche la création d'instance }
Les classes utilitaires peuvent-elles contenir un état ?
Non. Si une classe utilitaire contient un état (champs d'instance ou statiques), cela viole le principe de rédaction d'utilitaires, entraîne des erreurs de multithreading et nuit à la lisibilité.
Peut-on moquer les méthodes statiques des classes utilitaires lors des tests ?
Seulement à l'aide d'outils spéciaux comme PowerMock, qui rendent les tests plus complexes et parfois instables. Dans les cas ordinaires, une approche compatible DI avec une instance est préférable pour les tests.
Dans le projet, tous les services sont implémentés à l'aide de méthodes statiques utilitaires. L'injection de dépendances est impossible, les tests unitaires ne sont pas isolés, chaque test dépend de l'état de l'environnement.
Avantages :
Inconvénients :
Dans les services, on utilise des classes distinctes avec injection de dépendances, via des interfaces. Pour les transformations et les opérations simples, des classes utilitaires sans état sont utilisées.
Avantages :
Inconvénients :