Au cours des derniers mois, je suis tombé plusieurs fois sur la technique / le schéma suivant. Cependant, je n'arrive pas à trouver un nom spécifique, et je ne suis pas sûr à 100% de tous ses avantages et inconvénients.
Le schéma se présente comme suit:
Dans une interface Java, un ensemble de méthodes communes est défini comme d'habitude. Cependant, en utilisant une classe interne, une instance par défaut est divulguée via l'interface.
public interface Vehicle {
public void accelerate();
public void decelerate();
public static class Default {
public static Vehicle getInstance() {
return new Car(); // or use Spring to retrieve an instance
}
}
}
Pour moi, il semble que le plus grand avantage réside dans le fait qu'un développeur n'a besoin que de connaître l'interface et non ses implémentations, par exemple au cas où il souhaiterait rapidement créer une instance.
Vehicle someVehicle = Vehicle.Default.getInstance();
someVehicle.accelerate();
De plus, j'ai vu cette technique utilisée avec Spring afin de fournir dynamiquement des instances en fonction de la configuration. À cet égard, il semble également que cela puisse aider à la modularisation.
Néanmoins, je ne peux pas secouer le sentiment qu'il s'agit d'une mauvaise utilisation de l'interface car elle couple l'interface avec l'une de ses implémentations. (Principe d'inversion des dépendances, etc.) Quelqu'un pourrait-il m'expliquer comment s'appelle cette technique, ainsi que ses avantages et ses inconvénients?
Mise à jour:
Après un certain temps de réflexion, j'ai revérifié et remarqué que la version singleton suivante du modèle était utilisée beaucoup plus souvent. Dans cette version, une instance statique publique est exposée via l'interface qui n'est initialisée qu'une seule fois (car le champ est final). De plus, l'instance est presque toujours récupérée à l'aide de Spring ou d'une fabrique générique qui dissocie l'interface de l'implémentation.
public interface Vehicle {
public void accelerate();
public void decelerate();
public static class Default {
public static final Vehicle INSTANCE = getInstance();
private static Vehicle getInstance() {
return new Car(); // or use Spring/factory here
}
}
}
// Which allows to retrieve a singleton instance using...
Vehicle someVehicle = Vehicle.Default.INSTANCE;
En bref: il semble qu'il s'agisse d'un modèle singleton / factory personnalisé, qui permet essentiellement d'exposer une instance ou un singleton via son interface. En ce qui concerne les inconvénients, quelques-uns ont été nommés dans les réponses et commentaires ci-dessous. Jusqu'à présent, l'avantage semble résider dans sa commodité.
Vehicle.Default
être déplacé vers le haut dans l'espace de noms du package en tant que classe d'usine, par exemple VehicleFactory
.
Vehicle.Default.getInstance() != Vehicle.Default.getInstance()