web-dev-qa-db-fra.com

Quel est le nom du modèle suivant (anti)? Quels sont ses avantages et ses inconvénients?

Au cours des derniers mois, j'ai trébuché quelques fois sur la technique/motif suivante. Cependant, je n'arrive pas à trouver un nom spécifique, je ne suis que 100% sûr de tous ses avantages et ses inconvénients.

Le modèle va comme suit:

Dans A Java Interface, un ensemble de méthodes communes est définie comme d'habitude. Toutefois, à l'aide d'une classe interne, une instance par défaut est divulguée à travers 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 gros 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 ex. au cas où il veut rapidement créer une instance.

 Vehicle someVehicle = Vehicle.Default.getInstance();
 someVehicle.accelerate();

En outre, j'ai vu cette technique utilisée avec le printemps afin de fournir de manière dynamique des instances en fonction de la configuration. À cet égard, il semble également que cela puisse aider à la modularisation.

Néanmoins, je ne peux pas bien secouer que ceci est une mauvaise utilisation de l'interface puisqu'elle coule l'interface avec l'une de ses implémentations. (principe d'inversion de dépendance, etc.) Quelqu'un peut-il m'expliquer comment cette technique est appelée, ainsi que ses avantages et ses inconvénients?

Mise à jour :

Après un certain temps pour examen, je revue et remarqua 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 initialisée une seule fois (en raison du dernier étant final). De plus, l'instance est presque toujours extraite à l'aide d'un ressort ou d'une usine générique qui découle l'interface de la mise en œuvre.

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 un mot: Il semble qu'il s'agisse d'un modèle personnalisé singleton/usine, qui permet essentiellement d'exposer une instance ou un singleton à travers son interface. En ce qui concerne les inconvénients, quelques-uns ont été nommés dans les réponses et les commentaires ci-dessous. Jusqu'à présent, l'avantage semble mentir dans sa commodité.

28
Jérôme

Default.getInstance Est imho juste une forme très spécifique de A méthode d'usine , mêlée à une convention de dénomination prise du modèle singleton (mais sans être une implémentation de le dernier). Dans la forme en cours, il s'agit d'une violation du " principe de responsabilité unique ", car l'interface (qui permet déjà de déclarer une API de classe) prend la responsabilité supplémentaire de fournir une instance par défaut, qui serait être bien mieux placé dans une classe distincte VehicleFactory.

Le principal problème causé par cette construction est qu'il induit une dépendance cyclique entre Vehicle et Car. Par exemple, dans la forme actuelle, il ne sera pas possible de placer Vehicle dans une bibliothèque et Car dans un autre. Utilisation d'une classe d'usine distincte et de placer la méthode Default.getInstance Il y aurait résoudre ce problème. Il peut également être une bonne idée de donner à cette méthode un nom différent, d'empêcher toute confusion liée aux singletons. Donc le résultat pourrait être quelque chose comme

VehicleFactory.createDefaultInstance()

24
Doc Brown

Cela ressemble à objet nul motif à moi.

Mais cela dépend fortement de la manière dont la classe Car est mise en œuvre. S'il est implémenté de manière "neutre", il s'agit bien d'un objet nul. Cela signifie que si vous pouvez supprimer toutes les vérifications nulles sur l'interface et mettre de l'instance de cette classe au lieu de chaque occurrence de null, le code doit alors fonctionner correctement.

De plus, si c'est ce modèle, il n'y a pas de problème de création d'un couplage étroit entre l'interface elle-même et la mise en œuvre de l'objet NULL. Parce que Null Object peut être partout où ladite interface est utilisée.

3
Euphoric