DAO versus repository-patronen
Vaak worden de implementaties van repository en DAO als onderling uitwisselbaar beschouwd, vooral in datacentrische apps. Dit zorgt voor verwarring over hun verschillen.
In dit artikel bespreken we de verschillen tussen DAO- en Repository-patronen.
2. DAO-patroon
Het Data Access Object Pattern, ook bekend als DAO-patroon, is een abstractie van gegevenspersistentie en wordt beschouwd als dichter bij de onderliggende opslag, die vaak tabelgeoriënteerd is.
Daarom komen onze DAO's in veel gevallen overeen met databasetabellen, waardoor het een eenvoudiger manier is om gegevens uit de opslag te verzenden / op te halen en de lelijke zoekopdrachten te verbergen.
Laten we eens kijken naar een eenvoudige implementatie van het DAO-patroon.
2.1. Gebruiker
Laten we eerst een basis maken Gebruiker domeinklasse:
openbare klasse Gebruiker {privé Lange id; private String gebruikersnaam; private String voornaam; privé String-e-mail; // getters en setters}
2.2. Gebruiker
Vervolgens maken we het Gebruiker interface die eenvoudige CRUD-bewerkingen biedt voor het Gebruiker domein:
openbare interface User Dao {void create (User user); Gebruiker gelezen (lange id); ongeldige update (gebruiker gebruiker); void delete (String gebruikersnaam); }
2.3. GebruikersdateImpl
Als laatste maken we het GebruikersdateImpl klasse die de Gebruiker koppel:
public class UserensionalImpl implementeert User Dao {private final EntityManager entityManager; @Override public void create (User user) {entityManager.persist (user); } @Override public User read (lange id) {return entityManager.find (User.class, id); } // ...}
Hier hebben we voor de eenvoud de JPA gebruikt EntityManager interface om te communiceren met onderliggende opslag en om een gegevenstoegangsmechanisme te bieden voor het Gebruiker domein.
3. Repository-patroon
Volgens het boek van Eric Evans Domeingestuurd ontwerp, de "Repository is een mechanisme voor het inkapselen van opslag-, ophaal- en zoekgedrag, dat een verzameling objecten emuleert."
Evenzo, volgens Patronen van Enterprise Application Architecture, het "Bemiddelt tussen de domein- en gegevenstoewijzingslagen met behulp van een collectie-achtige interface voor toegang tot domeinobjecten."
Met andere woorden, een repository behandelt ook gegevens en verbergt query's die vergelijkbaar zijn met DAO. Het bevindt zich echter op een hoger niveau, dichter bij de bedrijfslogica van een app.
Bijgevolg kan een repository een DAO gebruiken om gegevens uit de database op te halen en een domeinobject te vullen. Of het kan de gegevens van een domeinobject voorbereiden en naar een opslagsysteem sturen met behulp van een DAO voor persistentie.
Laten we eens kijken naar een eenvoudige implementatie van het repository-patroon voor het Gebruiker domein.
3.1. UserRepository
Laten we eerst het UserRepository koppel:
openbare interface UserRepository {User get (lange id); void add (gebruiker gebruiker); ongeldige update (gebruiker gebruiker); ongeldig verwijderen (gebruiker gebruiker); }
Hier hebben we een paar veelgebruikte methoden toegevoegd, zoals krijgen, toevoegen, bijwerken, en verwijderen om te werken met de verzameling objecten.
3.2. UserRepositoryImpl
Vervolgens maken we het UserRepositoryImpl klasse die een implementatie biedt van de UserRepository koppel: Hier hebben we de GebruikersdateImpl om gegevens uit de database te verzenden / op te halen. Tot nu toe kunnen we zeggen dat de implementaties van DAO en repository erg op elkaar lijken omdat de Gebruiker klasse is een bloedarm domein. En een repository is gewoon een andere laag over de datatoegangslaag (DAO). DAO lijkt echter een perfecte kandidaat om toegang te krijgen tot de gegevens, en een repository is een ideale manier om een zakelijke use-case te implementeren. Laten we, om de laatste verklaring duidelijk te begrijpen, onze verbeteren Gebruiker domein om een zakelijk gebruiksscenario af te handelen. Stel je voor dat we een socialemediaprofiel van een gebruiker willen voorbereiden door zijn Twitter-tweets, Facebook-berichten en meer te verzamelen. Eerst maken we het Tweet klasse met een paar eigenschappen die de tweet-informatie bevatten: Dan, vergelijkbaar met de Gebruiker, maken we de Tweeten interface waarmee tweets kunnen worden opgehaald: Evenzo zullen we het TweetensionalImpl klasse die de implementatie van de fetchTweets methode: Hier zullen we Twitter-API's aanroepen om alle tweets van een gebruiker op te halen met zijn e-mail. In dit geval biedt een DAO dus een gegevenstoegangsmechanisme met behulp van API's van derden. Laten we als laatste het UserSocialMedia subklasse van onze Gebruiker class om een lijst bij te houden van de Tweet voorwerpen: Hier, onze UserSocialMedia class is een complex domein dat de eigenschappen van de Gebruiker domein ook. Nu gaan we onze UserRepositoryImpl klasse om een Gebruiker domeinobject samen met een lijst met tweets: Hier de UserRepositoryImpl extraheert gebruikersgegevens met behulp van de GebruikersdateImpl en tweets van gebruikers met de TweetensionalImpl. Vervolgens verzamelt het beide sets informatie en levert het een domeinobject van het UserSocialMedia klasse die handig is voor onze zakelijke use-case. Daarom een repository vertrouwt op DAO's voor toegang tot gegevens uit verschillende bronnen. Op dezelfde manier kunnen we onze Gebruiker domein om een lijst met Facebook-berichten bij te houden. Nu we de nuances van de DAO- en Repository-patronen hebben gezien, zullen we hun verschillen samenvatten: Als we een anemisch domein hebben, is de repository ook slechts een DAO. Bovendien, het repository-patroon stimuleert een domeingestuurd ontwerp, waardoor ook niet-technische teamleden gemakkelijk de gegevensstructuur kunnen begrijpen. In dit artikel hebben we de verschillen tussen DAO- en repository-patronen onderzocht. Eerst hebben we een basisimplementatie van het DAO-patroon onderzocht. Toen zagen we een vergelijkbare implementatie met behulp van het Repository-patroon. Als laatste hebben we gekeken naar een repository die gebruikmaakt van meerdere DAO's, waardoor de mogelijkheden van een domein worden vergroot om een zakelijk gebruik op te lossen. Daarom kunnen we concluderen dat het Repository-patroon een betere aanpak is wanneer een app verandert van datacentrisch naar bedrijfsgericht. Zoals gewoonlijk zijn alle code-implementaties beschikbaar op GitHub.openbare klasse UserRepositoryImpl implementeert UserRepository {privé User DaoImpl userbaoImpl; @Override openbare gebruiker get (lange id) {gebruiker gebruiker = userbaoImpl.read (id); terugkeer gebruiker; } @Override public void add (User user) {userensionalImpl.create (user); } // ...}
4. Repository-patroon met meerdere DAO's
4.1. Tweet
openbare klasse Tweet {privé String e-mail; privé String tweetText; privé Date dateCreated; // getters en setters}
4.2. Tweeten en TweetensionalImpl
openbare interface Tweetbao {List fetchTweets (String e-mail); }
public class Tweet DaoImpl implementeert Tweet Dao {@Override public List fetchTweets (String e-mail) {List tweets = new ArrayList (); // roep Twitter API aan en bereid tweets voor om tweets terug te sturen; }}
4.3. Verbeteren Gebruiker Domein
openbare klasse UserSocialMedia breidt User {privélijst tweets uit; // getters en setters}
4.4. UserRepositoryImpl
openbare klasse UserRepositoryImpl implementeert UserRepository {privé User DaoImpl userbaoImpl; privé Tweet DaoImpl tweetbaoImpl; @Override openbare gebruiker get (lange id) {UserSocialMedia gebruiker = (UserSocialMedia) user DaoImpl.read (id); Lijst tweets = tweetensionalImpl.fetchTweets (user.getEmail ()); user.setTweets (tweets); terugkeer gebruiker; }}
5. Vergelijking van de twee patronen
6. Conclusie