La séparation entre la conception de l'API et leur mise en œuvre est souvent recommandée dans les grandes implémentations logicielles. Mais quelque part, ils doivent être reconnectés (c'est-à-dire que la mise en œuvre doit être reconnectée à l'API).
L'exemple suivant montre une conception de l'API et une invocation de sa mise en œuvre via l'objet d'instance: P>
import java.util.List; public abstract class Separation { public static final Separation INSTANCE = new SeparationImpl(); // Defining a special list public static interface MySpecialList<T> extends List<T> { void specialAdd(T item); } // Creation of a special list public abstract <T> MySpecialList<T> newSpecialList(Class<T> c); // Merging of a special list public abstract <T> MySpecialList<? extends T> specialMerge( MySpecialList<? super T> a, MySpecialList<? super T> b); // Implementation of separation public static class SeparationImpl extends Separation { @Override public <T> MySpecialList<T> newSpecialList(Class<T> c) { return ...; } @Override public <T> MySpecialList<? extends T> specialMerge( MySpecialList<? super T> a, MySpecialList<? super T> b) { return ...; } } }
4 Réponses :
Une technique qui utilise souvent à OSGI est de disposer de l'API dans un module distinct à la mise en œuvre. L'API devrait compiler en lui-même en évitant toute référence à la mise en œuvre directement. P>
Est-ce une nécessité absolue pour Osgi ou juste de bonnes pratiques?
Utiliser certains des cadres tels que l'iPojo, c'est nécessaire, mais vous n'avez pas à le faire dans tous les cas (et je ne le fais pas)
J'ai toujours compris l'obligation de séparer l'interface de la mise en œuvre pour signifier que vous ne mélangez pas le comment em> de votre implémentation avec le quel em>. Donc, dans votre exemple ci-dessus, mélanger API et la mise en œuvre signifieraient exposer dans l'API quelque chose qui était spécifique à la mise en œuvre de votre API. p>
À titre d'exemple, examinez comment l'itération est mise en œuvre dans diverses classes de collecte. Il existe des moyens plus spécifiques que vous pouvez récupérer des éléments dans des collections spécifiques (par exemple, par la position dans une arrachelist), mais ceux-ci ne sont pas exposés dans J'ai également vu des projets avec d'énormes répertoires d'interfaces, chacune ayant une seule implémentation concrète et chacune desquelles reproduit mécaniquement chaque méthode dans leur mise en œuvre concrète, qui semble être une abstraction "prétendre" complètement inutile, telle qu'elle est ne fournissant pas une abstraction logique. p> Collection code> car ils sont spécifiques à la mise en œuvre de la mise en oeuvre concrète. P >
Les réponses de Peter et Steve sont suffisantes, mais je voudrais ajouter plus - si vous n'avez jamais eu qu'une seule implémentation de l'interface ou de la classe abstraite, alors son inutile d'avoir une interface ou une classe abstraite comme étant la défaite du but de l'abstraction.
de comme la bibliothèque de collecte standard p>
Dans votre cas, je n'ai vraiment pas compris - pourquoi vous avez mis en œuvre Séparation code> en tant que classe abstrait, plutôt
SéparationMpl code> peut être une classe API ou si vous avez des implémentations différentes
Séparation code> peut être une introtrface et si vous avez une fonctionnalité commune, vous pouvez avoir une autre classe abstraite implémentant votre interface, puis
SéparationMpl code> hériter de cette classe abstraite. La hiérarchie de la classe d'échantillons ressemblerait à
Même s'il n'y a qu'une seule implémentation de production, les ABC et les interfaces sont toujours souvent une bonne chose; Premièrement, ils appliquent la séparation propre des préoccupations. Deuxièmement, ils permettent des tests d'unités faciles via des simulacres.
J'essayais d'illustrer le fait que parfois, vous avez besoin d'accéder à une instanciation d'une API et d'une manière consiste à la fournir de l'API elle-même. Je suis d'accord, cela aurait pu être fait avec une interface uniquement.
@Oli Charlesworth - Nous pouvons se moquer des classes concrètes, aucune interface pour un but moqueur au moins.
@Premraj Comment garantissez-vous que l'API moquée correspond à l'API implémenté? Avec interfaces c'est trivial. Une mocke est elle-même une implémentation simple et dénudée, donc en ayant une maquette que vous avez une deuxième mise en œuvre.
En plus des bons points des autres auteurs, je mentionnerais les objectifs de test de l'unité: P>
à maquette des objets est très facile lorsque vous disposez d'interfaces intégrées de classes. P>