Я разрабатываю RESTful API, и я думаю, что для моих ресурсов удобно использовать DAO, потому что, хотя я планирую просто использовать память для их хранения, я не хочу закрывать дверь тому, кто использует мою библиотеку, если они решили использовать реализация базы данных для DAO.
Мой вопрос заключается в том, должен ли DAO быть одиночным или нет. Если это не так, у службы будет экземпляр DAO, и он будет выглядеть примерно так:
@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);
}
}
Хотя, если бы DAO был синглтоном, я думаю, что не было бы большой разницы, только в первой строке:
private IEventSchedulerDao dao = EventSchedulerDao.getInstance();
Я все еще должен был бы использовать IEventSchedulerDao
экземпляр, но я предполагаю, что все одиночные игры работают как это правильно? По какой-то причине я всегда сопоставляю синглтоны со статическими методами, поэтому вместо того, чтобы одноэлементный экземпляр был видим для пользователя getInstance()
, он будет скрыт, и он / она будет просто использовать EventSchedulerDao.get(name)
и т. Д. ... в статическом режиме. Это вещь или это только я?
Итак, я должен или не должен иметь одиночные DAO?
И как побочный вопрос, хорошо ли мой подход, чтобы у пользователя были открытые двери для реализации своих собственных DAO?
Ответы:
Я бы не использовал синглтон. Это признанный анти-паттерн , который затрудняет тестирование. Я бы предпочел внедрить в конкретную реализацию и сделать так, чтобы ваш сервис ссылался на интерфейс DAO (позволяя вам внедрять различные реализации в)
источник
private IEventSchedulerDao dao = new EventSchedulerDao();
, где вы ошиблись. Реализация forIEventSchedulerDao
должна быть введена через конструктор и никогда не изменяться (т.е. избавляться от нееsetEventSchedulerDao
тоже).D ата ступа O ▪ Таблица должна только действительно существует один раз в вашем приложении. Логика остается той же, единственное, что отличается, это значения, входящие и выходящие из методов, которые предоставляет DAO.
Имея это в виду, очевидно, что первое, что обычно происходит, это реализация DAO как сильного синглтона , то есть когда у вас есть
static
метод в классе фабрики, что-то вродеgetInstance
ленивой загрузки экземпляра DAO, если он нулевой, и его возвращения.Извините, если синтаксис не совсем правильный, я не программист на Java.
Это невероятно сложно проверить, потому что вы не можете поменять реализацию без изменения кода
UsesDao
класса. Это можно сделать с помощью некоторого исправления , но обычно это не считается хорошей практикой.Тогда есть лучший способ, слабый шаблон синглтона , где вы не извлекаете экземпляр с помощью
static
метода, а делаете так, чтобы все классы зависели от экземпляра с помощью конструктора или метода установки (в вашем случаеEventSchedulerService
вы используете инъекцию метода установки).Единственная проблема заключается в том, что вам необходимо убедиться, что все классы, которые зависят от экземпляра класса, который должен существовать только один раз в жизненном цикле вашего приложения, принимают тот же экземпляр, что и их параметр, т.е.
new
вызывается только один раз на объект DAO во всем приложении.Очевидно, что это невероятно сложно отследить, и построение граф-объекта является утомительной и раздражающей работой.
К счастью, есть контейнеры IoC , которые делают это намного проще. Помимо Spring , контейнер Guice IoC от Google довольно популярен среди Java-программистов.
При использовании контейнера IoC вы настраиваете его на определенное поведение, т.е. вы указываете, как предполагается создать определенные классы и требуется ли какой-либо класс в качестве зависимости, как должна выглядеть зависимость (должна ли она быть всегда новым экземпляром или единичным объектом) и контейнер связывает все это.
Вы можете проверить эту ссылку для одного примера с Guice.
Плюсы и минусы использования контейнера IoC
Pros
Cons
источник
Синглтон ссылается на концепцию только одного экземпляра и способа получить доступ к экземпляру (через столь известный статический метод getInstance () )
Но за всем этим есть еще пример. Построенный объект с ограниченным доступом.
В вашем случае я бы предпочел использовать подход DI (внедрение зависимостей). Как и первый блок кода, который вы раскрыли. Просто небольшое изменение. Внедрить DAO через конструктор. Удалять или нет сеттер зависит от вас. Если вы хотите защитить контроллер от изменений во время выполнения, удалите его. Если вы хотите предложить такую возможность, то сохраните ее.
Вы правильно используете интерфейс и предлагаете открытое окно для дальнейшей реализации DAO. Может или не нужно. Это займет всего одну минуту больше работы, но это делает ваш дизайн гибким. Ваш в памяти DAO довольно распространен. Очень полезно, как макет во время тестирования. Или как стандартная реализация DAO.
Просто намек. Статические ресурсы (объекты, методы, константы или переменные) похожи на глобальные ресурсы. Если глобальные злые или нет, это вопрос потребностей или вкусов. Однако с ними связаны неявные недостатки. Они связаны с параллелизмом , безопасностью потоков (в Java, не знаю о других языках), сериализацией ...
Поэтому я бы предложил использовать статику осторожно
источник