DAO vs Repository Patterns
Implementering av repository og DAO blir ofte ansett som utskiftbare, spesielt i datasentriske apper. Dette skaper forvirring om forskjellene deres.
I denne artikkelen vil vi diskutere forskjellene mellom DAO og Repository mønstre.
2. DAO-mønster
Data Access Object Pattern, aka DAO mønster, er en abstraksjon av datapresistens og regnes som nærmere den underliggende lagringen, som ofte er bordsentrert.
Derfor, i mange tilfeller, samsvarer DAO-ene våre med databasetabeller, slik at en enklere måte å sende / hente data fra lagring på, skjuler de stygge spørsmålene.
La oss undersøke en enkel implementering av DAO-mønsteret.
2.1. Bruker
La oss først lage en grunnleggende Bruker domeneklasse:
offentlig klasse bruker {privat Lang id; privat streng brukernavn; privat streng fornavn; privat streng e-post; // getters og setters}
2.2. UserDao
Deretter lager vi UserDao grensesnitt som gir enkle CRUD-operasjoner for Bruker domene:
offentlig grensesnitt UserDao {void create (brukerbruker); Brukerleset (Lang id); ugyldig oppdatering (brukerbruker); ugyldig sletting (String brukernavn); }
2.3. UserDaoImpl
Til slutt lager vi UserDaoImpl klasse som implementerer UserDao grensesnitt:
offentlig klasse UserDaoImpl implementerer UserDao {private final EntityManager entityManager; @ Overstyr offentlig tomrom opprette (brukerbruker) {entityManager.persist (bruker); } @ Override public User read (long id) {return entityManager.find (User.class, id); } // ...}
Her, for enkelhets skyld, har vi brukt JPA EntityManager grensesnitt for å samhandle med underliggende lagring og gi en datatilgangsmekanisme for Bruker domene.
3. Depotmønster
I henhold til Eric Evans 'bok Domenedrevet design, den "Repository er en mekanisme for innkapsling av lagring, henting og søkeatferd, som etterligner en samling objekter."
Likeledes ifølge Mønstre av Enterprise Application Architecture, den “Formidler mellom domenet og datakartingslagene ved hjelp av et samlingsliknende grensesnitt for tilgang til domeneobjekter.”
Med andre ord håndterer et depot også data og skjuler spørsmål som ligner på DAO. Imidlertid sitter den på et høyere nivå, nærmere forretningslogikken til en app.
Derfor kan et depot bruke en DAO til å hente data fra databasen og fylle ut et domeneobjekt. Eller det kan klargjøre dataene fra et domeneobjekt og sende dem til et lagringssystem ved hjelp av en DAO for utholdenhet.
La oss undersøke en enkel implementering av depotmønsteret for Bruker domene.
3.1. UserRepository
La oss først lage UserRepository grensesnitt:
offentlig grensesnitt UserRepository {User get (Long id); void add (brukerbruker); ugyldig oppdatering (brukerbruker); ugyldig fjerne (brukerbruker); }
Her har vi lagt til noen vanlige metoder som få, legge til, Oppdater, og fjerne å jobbe med samling av objekter.
3.2. UserRepositoryImpl
Deretter lager vi UserRepositoryImpl klasse som gir en implementering av UserRepository grensesnitt: Her har vi brukt UserDaoImpl for å sende / hente data fra databasen. Så langt kan vi si at implementeringene av DAO og repository ser veldig like ut fordi Bruker klasse er et anemisk domene. Og et depot er bare et lag over datatilgangslaget (DAO). Imidlertid virker DAO som en perfekt kandidat for å få tilgang til dataene, og et depot er en ideell måte å implementere en forretningsbruk. For å forstå den siste uttalelsen, la oss forbedre vår Bruker domene for å håndtere et forretningsbruk. Tenk deg at vi vil lage en sosial medieprofil for en bruker ved å samle Twitter-tweets, Facebook-innlegg og mer. Først skal vi lage kvitring klasse med noen få egenskaper som inneholder tweetinformasjonen: Så, i likhet med UserDao, lager vi TweetDao grensesnitt som gjør det mulig å hente tweets: På samme måte lager vi TweetDaoImpl klasse som gir implementering av fetchTweets metode: Her vil vi ringe Twitter APIer for å hente alle tweets av en bruker ved hjelp av e-posten sin. Så i dette tilfellet gir en DAO en datatilgangsmekanisme ved bruk av tredjeparts APIer. Sist, la oss lage UserSocialMedia underklasse av vår Bruker klasse for å føre en liste over kvitring gjenstander: Her, vår UserSocialMedia klasse er et komplekst domene som inneholder egenskapene til Bruker domene også. Nå oppgraderer vi vår UserRepositoryImpl klasse for å gi en Bruker domeneobjekt sammen med en liste over tweets: Her, den UserRepositoryImpl trekker ut brukerdata ved hjelp av UserDaoImpl og brukerens tweets ved hjelp av TweetDaoImpl. Deretter samler det begge settene med informasjon og gir et domeneobjekt av UserSocialMedia klasse som er nyttig for vårt forretningsbruk. Derfor, et depot er avhengig av DAO for tilgang til data fra forskjellige kilder. På samme måte kan vi forbedre vår Bruker domene for å holde en liste over Facebook-innlegg. Nå som vi har sett nyansene i DAO og Repository-mønstrene, la oss oppsummere forskjellene deres: Også, hvis vi har et anemisk domene, vil depotet bare være en DAO. I tillegg depotmønsteret oppmuntrer til et domenedrevet design, som også gir en enkel forståelse av datastrukturen for ikke-tekniske teammedlemmer. I denne artikkelen undersøkte vi forskjeller mellom DAO og Repository mønstre. Først undersøkte vi en grunnleggende implementering av DAO-mønsteret. Deretter så vi en lignende implementering ved hjelp av Repository-mønsteret. Til slutt så vi på et depot som bruker flere DAO-er, og forbedret mulighetene til et domene for å løse et forretningsbruk. Derfor kan vi konkludere med at depotmønsteret viser en bedre tilnærming når en app går fra å være datasentrisk til forretningsorientert. Som vanlig er alle kodeimplementeringene tilgjengelige på GitHub.offentlig klasse UserRepositoryImpl implementerer UserRepository {private UserDaoImpl userDaoImpl; @Override public User get (Long id) {User user = userDaoImpl.read (id); retur bruker; } @Override public void add (Brukerbruker) {userDaoImpl.create (bruker); } // ...}
4. Datamaskinmønster med flere DAOer
4.1. kvitring
offentlig klasse Tweet {private String email; privat streng tweetText; privat Dato dato Opprettet; // getters og setters}
4.2. TweetDao og TweetDaoImpl
offentlig grensesnitt TweetDao {List fetchTweets (streng e-post); }
offentlig klasse TweetDaoImpl implementerer TweetDao {@Override public List fetchTweets (String email) {List tweets = new ArrayList (); // ring Twitter API og forbered Tweets for retur av objektet; }}
4.3. Forbedre Bruker Domene
offentlig klasse UserSocialMedia utvider bruker {private List tweets; // getters og setters}
4.4. UserRepositoryImpl
offentlig klasse UserRepositoryImpl implementerer UserRepository {private UserDaoImpl userDaoImpl; privat TweetDaoImpl tweetDaoImpl; @Override public User get (Long id) {UserSocialMedia user = (UserSocialMedia) userDaoImpl.read (id); Liste tweets = tweetDaoImpl.fetchTweets (user.getEmail ()); user.setTweets (tweets); retur bruker; }}
5. Sammenligning av de to mønstrene
6. Konklusjon