Je suis en train de développer une API RESTful et je pense qu'il est pratique d'utiliser des DAO pour mes ressources, car même si je prévois d'utiliser uniquement de la mémoire pour les stocker, je ne veux pas fermer la porte à quiconque utilise ma bibliothèque s'il décide d'utiliser une implémentation de base de données pour le DAO.
Ma question est de savoir si le DAO doit être un singleton ou non. Si ce n'est pas le cas, le service aura une instance du DAO et il ressemblerait à peu près à ceci:
@Path("eventscheduler")
public class EventSchedulerService {
private IEventSchedulerDao dao = new EventSchedulerDao();
// in case a different implementation is to be used
public void setEventSchedulerDao(IEventSchedulerDao dao) {
this.dao = dao;
}
@Path("{uniqueName}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Tournament getTournament(@PathParam("name") String uniqueName) {
return dao.get(uniqueName);
}
@Path("create")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Tournament createTournament(Tournament tournament) {
return dao.create(tournament);
}
}
Alors que si le DAO était un singleton, mais je suppose qu'il n'y aurait pas beaucoup de différence, juste dans la première ligne:
private IEventSchedulerDao dao = EventSchedulerDao.getInstance();
Je devrais encore utiliser une IEventSchedulerDao
instance, mais je suppose que tous les singletons fonctionnent comme ça, non? Pour une raison quelconque, je corrèle toujours les singletons aux méthodes statiques, donc au lieu d'avoir une instance de singleton visible par l'utilisateur getInstance()
, cela serait caché et il / elle utiliserait simplement EventSchedulerDao.get(name)
, etc ... de manière statique. Est-ce une chose ou est-ce juste moi?
Alors, dois-je ou ne dois-je pas avoir des DAO singleton?
Et comme question secondaire, est-ce que mon approche est d'avoir des portes ouvertes pour que l'utilisateur implémente ses propres DAO?
Réponses:
Je n'utiliserais pas de singleton. C'est un anti-modèle reconnu et rend les tests difficiles. Je préfère de loin injecter dans une implémentation concrète, et demander à votre service de référencer une interface DAO (vous permettant d'injecter différentes implémentations dans)
la source
private IEventSchedulerDao dao = new EventSchedulerDao();
est l'endroit où vous vous êtes trompé. L'implémentation deIEventSchedulerDao
doit être injectée via le constructeur et ne doit jamais être modifiée (c'est-à-dire se débarrasser desetEventSchedulerDao
trop).A D ata A ccès O bjet ne devrait exister vraiment une fois dans votre application. La logique reste la même, les seules choses qui sont différentes sont les valeurs entrant et sortant des méthodes fournies par le DAO.
Dans cet esprit, la première chose qui se produit est évidemment d'implémenter le DAO en tant que singleton fort , c'est-à-dire lorsque vous avez une
static
méthode sur une classe d'usine, quelque chose commegetInstance
, paresseux charger une instance du DAO si elle est nulle et la renvoyer.Excusez-moi si la syntaxe n'est pas tout à fait correcte, je ne suis pas un programmeur Java.
C'est incroyablement difficile à tester, car vous ne pouvez pas échanger l'implémentation sans modifier le code de la
UsesDao
classe. Cela peut être fait grâce à quelques correctifs de singe , mais n'est généralement pas considéré comme une bonne pratique.Ensuite, il y a la meilleure façon, le modèle singleton faible , où vous ne récupérez pas une instance via une
static
méthode, mais faites en sorte que toutes les classes dépendent de l'instance via un constructeur ou un setter (dans votre cas,EventSchedulerService
vous utilisez l'injection de setter).Le seul problème est que vous devez alors vous assurer que toutes les classes, qui dépendent d'une instance de classe qui ne devrait exister qu'une fois le cycle de vie de votre application, prennent la même instance que leur paramètre, c'est-à-dire. l'
new
est appelée une seule fois sur l'objet DAO dans l'application.De toute évidence, cela est incroyablement difficile à suivre et la construction du graphique d'objet est un travail fastidieux et ennuyeux.
Heureusement, il existe des conteneurs IoC , ce qui le rend beaucoup plus facile. Outre Spring , le conteneur Guice IoC de Google est très populaire parmi les programmeurs Java.
Lorsque vous utilisez un conteneur IoC, vous le configurez pour se comporter d'une certaine manière, c'est-à-dire. vous dites si la façon dont elle est censée construire certaines classes et si une classe est requise en tant que dépendance, à quoi devrait ressembler la dépendance (que ce soit toujours une nouvelle instance ou un singleton) et le conteneur le relie.
Vous pouvez vérifier ce lien pour un exemple singleton avec Guice.
Avantages et inconvénients de l'utilisation d'un conteneur IoC
Avantages
Les inconvénients
la source
Singleton se réfère au concept d' une seule instance et à la façon d'accéder à l'instance (via la fameuse méthode statique getInstance () )
Mais il y a toujours un exemple derrière tout cela. Un objet construit avec une sorte d'accès restreint.
Dans votre cas, je préférerais une approche DI (injection de dépendance). Comme le premier bloc de code que vous avez exposé. Juste un petit changement. Injectez le DAO via le constructeur. C'est à vous de retirer ou non le passeur. Si vous souhaitez protéger le contrôleur des modifications de l'exécution, supprimez-le. Si vous voulez offrir une telle possibilité, gardez-la.
Vous avez raison d'utiliser une interface et d'offrir une fenêtre ouverte pour d'autres implémentations de DAO. Peut ou peut ne pas être nécessaire. Cela ne prend qu'une minute de plus, mais cela rend votre conception flexible. Votre DAO en mémoire est assez courant. Très utile comme maquette au moment des tests. Ou comme implémentation DAO par défaut.
Juste un indice. Les ressources statiques (objets, méthodes, constantes ou variables) sont comme des ressources globales. Si les globaux sont mauvais ou non, c'est une question de besoins ou de goûts. Cependant, il y a des lacunes implicites qui leur sont liées. Ceux-ci sont liés à la concurrence , à la sécurité des threads (en Java, je ne connais pas les autres langages), à la sérialisation ...
Je suggère donc d'utiliser la statique avec prudence
la source