Tworzę API RESTful i myślę, że wygodnie jest używać DAO dla moich zasobów, ponieważ chociaż planuję po prostu używać pamięci do ich przechowywania, nie chcę zamykać drzwi przed kimkolwiek, kto korzysta z mojej biblioteki, jeśli zdecydują się użyć implementacja bazy danych dla DAO.
Moje pytanie brzmi, czy DAO powinno być singlem, czy nie. Jeśli nie, usługa będzie miała instancję DAO i będzie wyglądać mniej więcej tak:
@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);
}
}
Chociaż jeśli DAO byłby singlem, ale myślę, że nie byłoby dużej różnicy, tylko w pierwszym wierszu:
private IEventSchedulerDao dao = EventSchedulerDao.getInstance();
Nadal musiałbym użyć IEventSchedulerDao
instancji, ale chyba wszystkie singletony działają w ten sposób, prawda? Z jakiegoś powodu zawsze koreluję singletony z metodami statycznymi, więc zamiast wyświetlania instancji singletonu dla użytkownika getInstance()
, byłoby to ukryte, a on / ona używałaby EventSchedulerDao.get(name)
itd. W sposób statyczny. Czy to coś, czy to tylko ja?
Czy powinienem, czy nie powinienem mieć singleton DAO?
I na marginesie, czy w porządku jest moje podejście do posiadania otwartych drzwi dla użytkownika do wdrożenia własnych DAO?
Odpowiedzi:
Nie użyłbym singletona. Jest to uznany anty-wzór i utrudnia testowanie. Wolałbym raczej wprowadzić konkretną implementację, a twoja usługa powinna odwoływać się do interfejsu DAO (pozwalając ci na wprowadzanie różnych implementacji)
źródło
private IEventSchedulerDao dao = new EventSchedulerDao();
jest tam, gdzie popełniłeś błąd. Implementacja dlaIEventSchedulerDao
powinna zostać wstrzyknięta przez konstruktor i nigdy nie zmieniana (tj. Pozbyć sięsetEventSchedulerDao
też).D ata ccess O bject powinna istnieć naprawdę tylko raz w swojej aplikacji. Logika pozostaje taka sama, jedyne, co się różni, to wartości przychodzące i wychodzące z metod zapewnianych przez DAO.
Mając to na uwadze, oczywiście pierwszą rzeczą, która zwykle się zdarza, jest implementacja DAO jako silnego singletona , to znaczy, gdy masz
static
metodę w klasie fabrycznej, coś w rodzajugetInstance
leniwego ładowania instancji DAO, jeśli jest zerowa i zwracania jej.Przepraszam, jeśli składnia jest nieprawidłowa, nie jestem programistą Java.
Jest to niezwykle trudne do przetestowania, ponieważ nie można zamienić implementacji bez zmiany kodu
UsesDao
klasy. Można to zrobić poprzez łatanie małp , ale ogólnie nie jest to uważane za dobrą praktykę.Jest też lepszy sposób, słaby wzorzec singletonu , w którym nie odzyskujesz instancji za pomocą
static
metody, ale uzależniasz wszystkie klasy od instancji poprzez konstruktor lub seter (w twoimEventSchedulerService
przypadku używasz iniekcji setera).Jedynym problemem jest to, że musisz upewnić się, że wszystkie klasy, które zależą od instancji klasy, która powinna istnieć tylko po cyklu życia aplikacji, przyjmują tę samą instancję jako parametr, tj.
new
jest wywoływana tylko raz na obiekt DAO w całej aplikacji.Oczywiście, śledzenie tego jest niezwykle trudne, a konstruowanie wykresu obiektowego jest żmudną i irytującą pracą.
Na szczęście istnieją pojemniki IoC , które znacznie to ułatwiają. Oprócz wiosny , kontener Guice IoC firmy Google jest dość popularny wśród programistów Java.
Korzystając z kontenera IoC, konfigurujesz go tak, aby zachowywał się w określony sposób, tj. mówisz, czy ma ona konstruować pewne klasy i czy jakaś klasa jest wymagana jako zależność, jak powinna wyglądać zależność (czy powinna to być zawsze nowa instancja, czy singleton), a kontener łączy to wszystko.
Możesz sprawdzić ten link dla singletonowego przykładu z Guice.
Plusy i minusy korzystania z kontenera IoC
Plusy
Cons
źródło
Singleton odnosi się do koncepcji tylko jednej instancji i sposobu uzyskania dostępu do instancji (za pomocą tak znanej metody statycznej getInstance () )
Ale za tym wszystkim stoi jeszcze jeden przykład. Obiekt zbudowany z pewnego rodzaju ograniczonym dostępem.
W twoim przypadku wolę podejście DI (wstrzykiwanie zależności). Jak pierwszy odsłonięty blok kodu. Mała zmiana. Wstrzyknąć DAO za pomocą konstruktora. Aby usunąć lub nie setter zależy od ciebie. Jeśli chcesz chronić kontroler przed zmianami w środowisku wykonawczym, usuń go. Jeśli chcesz zaoferować taką możliwość, zachowaj ją.
Masz rację, korzystając z interfejsu i oferując otwarte okno na dalsze implementacje DAO. Może, ale nie musi być potrzebny. Zajmuje to tylko minutę pracy, ale sprawia, że Twój projekt jest elastyczny. Twoja pamięć DAO jest dość powszechna. Bardzo przydatny jako próbny w czasie testu. Lub jako domyślna implementacja DAO.
Tylko wskazówka. Zasoby statyczne (obiekty, metody, stałe lub zmienne) są jak zasoby globalne. Jeśli globale są złe, czy nie, jest to kwestią potrzeb lub gustów. Jednak wiążą się z nimi ukryte niedociągnięcia. Są one związane z współbieżnością , bezpieczeństwem wątków (w Javie, nie wiem o innych językach), serializacją ...
Sugerowałbym więc ostrożne używanie statyki
źródło