Чи повинен DAO бути однотонним чи ні?


14

Я розробляю API RESTful, і я думаю, що зручно використовувати 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?


Ви можете використовувати сингл-інтерфейс IoC замість синглета зі статичним аксесуаром.
CodesInChaos

Відповіді:


10

Я б не користувався одинаркою. Це визнаний антидіапазон і ускладнює тестування. Я б набагато скоріше вписав у конкретну реалізацію і мав би ваш сервісний довідник інтерфейс DAO (що дозволяє вводити різні реалізації у)


1
Що ви пропонуєте у своєму останньому реченні - це саме те, що я роблю правильно?
дабадаба

1
Ви посилання через інтерфейс (так), але ви не ін'єкційного дао (бути зрозуміло ....)
Brian Agnew

Що ви маєте на увазі? У мене є сетер для цього, чи не так?
dabadaba

@dabadaba Рядок private IEventSchedulerDao dao = new EventSchedulerDao();- це те, де ти помилився. Реалізацію для IEventSchedulerDaoслід вводити через конструктор і ніколи не змінювати (тобто позбуватися setEventSchedulerDaoтакож).
Девід Арно

Добре, я розумію. Я щойно зробив це, щоб надати DAO за замовчуванням і змінити його було б "необов'язково". Але прийняти вашу пропозицію означає мати конструктор для служби, відмінну від за замовчуванням, і, чесно кажучи, я не маю уявлення, як це відбувається з Джерсі, оскільки він використовує конструктор за замовчуванням. Ви випадково знаєте, як це зробити?
dabadaba

4

D ата ступа O ▪ Таблиця повинна тільки дійсно існує один раз у вашому додатку. Логіка залишається тією ж, єдиними речами є значення, що надходять та виходять із методів, які надає DAO.

Зважаючи на це, очевидно, що перше, що зазвичай трапляється, це реалізація DAO як сильного сингтона , тобто коли у вас є staticметод на фабричному класі, щось на кшталт getInstance, ледаче завантажуючи екземпляр DAO, якщо він недійсний, і повертати його.

Вибачте, якщо синтаксис не зовсім правий, я не Java-програміст.

class DaoSingletonFactory
{
    private static Dao dao = null;

    public static Dao getInstance()
    {
        if (DaoSingletonFactory.dao == null) {
            DaoSingletonFactory.dao = new Dao();
        }

        return DaoSingletonFactory.dao;
    }
}

class UsesDao
{
    public void someMethod()
    {
        Dao dao = DaoSingletonFactory.getInstance();
    }
}

Це надзвичайно важко перевірити, тому що ви не можете замінити реалізацію, не змінивши код UsesDaoкласу. Це можна зробити за допомогою деякого виправлення мавп , але це, як правило, не є доброю практикою.

Тоді є кращий спосіб, слабкий однотонний малюнок, коли ви не отримуєте екземпляр staticметодом, але всі класи залежать від екземпляра через конструктор або сеттер (у вашому випадку EventSchedulerServiceви використовуєте ін'єкцію сеттера).

Єдина проблема полягає в тому, що вам потім потрібно переконатися, що всі класи, які залежать від екземпляра класу, який повинен існувати лише після життєвого циклу вашої програми, приймають той самий екземпляр, що і їх параметр, тобто. newвикликається тільки один раз на об'єкт DAO в усьому додатку.

Очевидно, що це надзвичайно важко відстежувати, а побудова об'єкта-графіка - втомлива і дратівлива робота.

На щастя, є контейнери IoC , які значно полегшують його. Крім весни , Google-контейнер Guice IoC є досить популярним серед Java-програмістів.

Використовуючи контейнер IoC, ви налаштовуєте його так, щоб він поводився певним чином, тобто. Ви кажете, як слід будувати певні класи та чи потрібен якийсь клас як залежність, як залежність повинна виглядати (чи завжди це повинен бути новий екземпляр чи синглтон) і контейнер з'єднує це все.

Ви можете перевірити це посилання на однотонний приклад за допомогою Guice.


Плюси і мінуси використання контейнера IoC

Плюси

  • заощаджуючи бюджет, не потрібно писати всі заводські методи самостійно
  • (зазвичай) дуже відверта конфігурація
  • швидкий розвиток

Мінуси

  • магія чарівника, заняття якось побудовані, і ви насправді не можете зрозуміти, як це сталося
  • невеликий спад продуктивності завдяки пошуку класів (фабрики, написані вручну, будуть трохи швидшими)

1

Сінглтон розглядає концепцію лише одного екземпляра і спосіб отримати доступ до екземпляра (через так відомий статичний метод getInstance () )

Але за цим усе ще є примірник. Вбудований об’єкт із своєрідним відпочинковим доступом.

У вашому випадку я б скоріше скористався підходом DI (введення залежності). Як і перший блок коду, який ви відкрили. Просто невелика зміна. Введіть DAO через конструктор. Щоб видалити чи не встановити, ви вирішуєте. Якщо ви хочете захистити контролер від змін у процесі виконання, видаліть його. Якщо ви хочете запропонувати таку можливість, тоді зберігайте її.

Ви правильно користуєтеся Інтерфейсом і пропонуєте відкрите вікно для подальших втілень DAO. Може знадобитися чи не бути потрібним. Це займе лише хвилину більше роботи, але це робить ваш дизайн гнучким. Ваш DAO в пам'яті досить поширений. Дуже корисно як глузування під час тестування. Або як реалізація DAO за замовчуванням.

Просто натяк. Статичні ресурси (об'єкти, методи, константи або змінні) - це як глобальні ресурси. Якщо глобальні злі чи ні, це питання потреби чи смаку. Однак з ними пов'язані неявні недоліки. Вони пов'язані з паралельністю , безпекою потоків (на Java, не знаю про інші мови), серіалізацією ...

Тож я б запропонував обережно використовувати статику

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.