Ich entwickle eine RESTful-API und halte es für zweckmäßig, DAOs für meine Ressourcen zu verwenden, da ich, obwohl ich beabsichtige, nur Speicher zum Speichern dieser Ressourcen zu verwenden, nicht die Tür zu jedem schließen möchte, der meine Bibliothek verwendet, wenn er dies möchte eine Datenbankimplementierung für das DAO.
Meine Frage ist, ob das DAO ein Singleton sein soll oder nicht. Ist dies nicht der Fall, verfügt der Dienst über eine Instanz des DAO und sieht ungefähr so aus:
@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);
}
}
Wenn das DAO ein Singleton wäre, aber ich denke, es würde keinen großen Unterschied geben, nur in der ersten Zeile:
private IEventSchedulerDao dao = EventSchedulerDao.getInstance();
Ich müsste immer noch eine IEventSchedulerDao
Instanz verwenden, aber ich denke, alle Singletons funktionieren so, oder? Aus irgendeinem Grund korreliere ich Singletons immer mit statischen Methoden. Anstatt also eine Singleton-Instanz für den Benutzer sichtbar zu machen getInstance()
, wird diese ausgeblendet und er / sie verwendet nur EventSchedulerDao.get(name)
usw. auf statische Weise. Ist das eine Sache oder bin das nur ich?
Soll ich also einzelne DAOs haben oder nicht?
Und als Nebenfrage, ist es in Ordnung für mich, offene Türen zu haben, damit der Benutzer seine eigenen DAOs implementieren kann?
Antworten:
Ich würde keinen Singleton verwenden. Es ist ein anerkanntes Anti-Pattern und erschwert das Testen. Ich würde viel lieber eine konkrete Implementierung einbinden und Ihrem Dienst eine DAO-Schnittstelle zuweisen (mit der Sie verschiedene Implementierungen einbinden können).
quelle
private IEventSchedulerDao dao = new EventSchedulerDao();
ist, wo Sie falsch gegangen sind. Die Implementierung fürIEventSchedulerDao
sollte über den Konstruktor injiziert und niemals geändert werden (dh auch loswerdensetEventSchedulerDao
).A D ata A ccess O bject sollte in Ihrer Anwendung nur dann wirklich einmal existieren. Die Logik bleibt die gleiche, die einzigen Unterschiede sind die Werte, die in die vom DAO bereitgestellten Methoden ein- und ausgehen.
In diesem Sinne ist es offensichtlich das erste, was normalerweise passiert, das DAO als starken Singleton zu implementieren. Das heißt, wenn Sie eine
static
Methode für eine Factory-Klasse haben, die so etwas wie dasgetInstance
verzögerte Laden einer DAO-Instanz, wenn sie null ist, und das Zurückgeben derselben.Entschuldigen Sie, wenn die Syntax nicht ganz stimmt, ich bin kein Java-Programmierer.
Dies ist unglaublich schwer zu testen, da Sie die Implementierung nicht austauschen können, ohne den Code der
UsesDao
Klasse zu ändern . Dies kann durch das Patchen von Affen geschehen , wird jedoch im Allgemeinen nicht als gute Praxis angesehen.Dann gibt es den besseren Weg, das schwache Singleton- Muster, bei dem Sie keine Instanz über eine
static
Methode abrufen , sondern alle Klassen entweder über einen Konstruktor oder einen Setter von der Instanz abhängig machen (in Ihrem Fall verwendenEventSchedulerService
Sie die Setter-Injection).Das einzige Problem ist, dass Sie dann sicherstellen müssen, dass alle Klassen, die von einer Instanz der Klasse abhängen, die nur einmal in Ihrem Anwendungslebenszyklus vorhanden sein sollte, dieselbe Instanz wie ihr Parameter verwenden, d. H. Das
new
wird nur einmal auf dem DAO-Objekt in der gesamten Anwendung aufgerufen.Offensichtlich ist es unglaublich schwierig, dies zu verfolgen, und die Erstellung des Objektgraphen ist eine mühsame und lästige Arbeit.
Zum Glück gibt es IoC- Container, die es viel einfacher machen. Neben Spring ist der Guice IoC-Container von Google bei Java-Programmierern sehr beliebt.
Wenn Sie einen IoC-Container verwenden, konfigurieren Sie ihn so, dass er sich auf eine bestimmte Art und Weise verhält, z. Sie sagen, ob es bestimmte Klassen erstellen soll und ob eine Klasse als Abhängigkeit erforderlich ist, wie die Abhängigkeit aussehen soll (ob es sich immer um eine neue Instanz oder um einen Singleton handeln soll) und der Container verkabelt alles.
Sie können diesen Link für ein Singleton-Beispiel mit Guice überprüfen .
Vor- und Nachteile der Verwendung eines IoC-Containers
Vorteile
Nachteile
quelle
Singleton bezieht sich auf das Konzept nur auf eine Instanz und den Weg, um Zugriff auf die Instanz zu erhalten (durch die so berühmte statische Methode getInstance () )
Aber dahinter steckt noch eine Instanz. Ein gebautes Objekt mit einer Art eingeschränktem Zugriff.
In Ihrem Fall würde ich mich eher für den DI-Ansatz (Dependency Injection) entscheiden. Wie der erste Codeblock, den Sie verfügbar gemacht haben. Nur eine kleine Veränderung. Injizieren Sie das DAO über den Konstruktor. Zu entfernen oder nicht der Setter liegt bei Ihnen. Wenn Sie den Controller vor Änderungen in der Laufzeit schützen möchten, entfernen Sie ihn. Wenn Sie eine solche Möglichkeit anbieten wollen, dann behalten Sie sie.
Sie haben die Möglichkeit, ein Interface zu verwenden und ein offenes Fenster für weitere DAO-Implementierungen anzubieten. Kann oder kann nicht benötigt werden. Es dauert nur noch eine Minute und macht Ihr Design flexibel. Ihre im Gedächtnis DAO ist ziemlich verbreitet. Sehr nützlich als Mock zum Testen. Oder als Standard-DAO-Implementierung.
Nur ein Hinweis. Statische Ressourcen (Objekte, Methoden, Konstanten oder Variablen) sind wie globale Ressourcen. Ob Globales böse sind oder nicht, ist eine Frage der Bedürfnisse oder des Geschmacks. Es gibt jedoch implizite Mängel, die an sie gebunden sind. Diese beziehen sich auf Parallelität , Thread-Sicherheit (in Java keine Kenntnisse in anderen Sprachen), Serialisierung ...
Ich würde daher empfehlen, die Statik vorsichtig zu verwenden
quelle