2015-04-23 2 views
3

Я просматриваю некоторые классы DAO, где они подвергают статическим методам CRUD create(), delete() и т. Д. И т.д. в программу и где каждый класс DAO реализует шаблон Observer, проверяя для изменений в базе данных через класс Notification.java, и если одно уведомление об изменении получено, потянув объект из базы данных.Шаблон наблюдателя и классы DAO с статическими методами CRUD

Упрощенный код похож на это:

OfficeDAO.java

public class OfficeDAO implements PropertyChangeListener 
{ 
    public OfficeDAO() 
    { 
     /* 
     * Below we add ourselves to the observers of class Notifications 
     * (see observer pattern in Java) in practice we are notified 
     * when one of our objects is changed by a remote client user 
     */ 
     Notification.addChangeListener(this); 
    } 

    public static void create(Office office) 
    { 
     Connection connection = DBConnection.getConnection(); 

     //... stuff with the database insertion 

     Notification.notifyDatabaseChanges("ocreate-" + officeId); 
    } 
} 

Теперь проблема заключается в том, что addChangeListener (это); находится в конструкторе, но поскольку этот класс DAO используется через его статические методы, конструктор никогда не вызывается.

Чтобы исправить это в главном() метод применения (внутри нити EDT, кстати) есть вызов, как:

new OfficeDAO(); //ignore this, it is needed only to start the DAO constructor 

Это казалось вполне Hacky, поэтому я думал, добавив

static { 
    Notification.addChangeListener(this); 
} 

в классе OfficeDAO.java, но, разумеется, эта «эта» ссылка отсутствует в статическом инициализаторе, поэтому у меня нет решений. Извлечение статичности из методов DAO исключено из-за того, что эти методы вызывается по всему приложению и вызывается без экземпляра класса.

Есть ли какое-либо чистое решение или обходное решение, которое я в настоящее время отсутствует?

+0

Имеет ли PropertyChangeListener только статические методы, которые переопределены в каждом DAO? Можете ли вы показать код для PropertyChangeListener и класса Notification? Кроме того, в классическом шаблоне Observer это Observable уведомляет наблюдателей об изменении своего состояния. – CKing

ответ

0

DAO проектирования является очень сложным предметом, вы могли бы начать читать статью Balusc (пользователь на этом форуме) на DAO design и в конце концов, выбираете для основы, которая имеет дело с DAO, и управлением соединениями.

Очень тонкая библиотека, которая дает вам хорошее начало при правильной реализации DAO: Butterfly Persistence, она создаст DAOFactory и будет управлять соединением для вас без необходимости импортировать библиотеку баннеров Spring или Hibernate объемом 100 МБ.

Что касается добавления слушателей и уведомлений для операций с базой данных, вы должны полностью избежать этого и вместо этого использовать базу данных, которая поддерживает уведомление о событиях, такое как Oracle или Firebird.

Таким образом вы только слушаете события, и база данных уведомляет вас о любых изменениях в ее таблицах.

2

Это, кажется, довольно грязный сценарий, создание нового объекта только для добавления слушателя в уведомление кажется скорее анти-шаблоном. Мое предположение заключается в том, что это часть некоторого устаревшего кода, и не так много повторного факторинга кода. Я мог бы сказать, что, поскольку слой DAO действует больше как одноэлементный, вы можете встроить предварительно созданный экземпляр DAO и получить доступ к нему с помощью статической ссылки.

private static OfficeDAO myDAO = new OfficeDAO(); //The constructor code remains the same 
+0

Да, это какой-то старый код, который можно было бы реорганизовать, если бы я был уверен в том, как это сделать, так как это довольно много DAO и проект сам довольно большой. Если бы я сделал DAO как статический, я бы сломал Notification.addChangeListener (это); которые критически важны для правильной работы приложения. –

+0

@ sarah.ferguson Я не думаю, что вам нужно сделать «статическую» DAO. Целью этого ответа является объяснение того, что вы можете иметь ссылку «статический» на ваш DAO, а не просто «новый DAO()»; Хотя это сделает код менее отвратительным, он, безусловно, будет контрпродуктивным. Зачем обращаться к статическим методам, используя ссылку класса? Ваша IDE добавит предупреждения об этом по всему вашему коду. – CKing

0

Вы можете изменить все ваши классы DAO на Singleton. Я согласен с тем, что нет необходимости создавать экземпляр DAO, поскольку ваши DAO не имеют состояния, и это не идеальное решение. Но опять же, вы не ищете идеальное решение, а более чистый взлом с минимальными изменениями, требуемыми в клиентском коде. Я не уверен, что вы используете инфраструктуру IoC в своем проекте, но если вы решите использовать ее в будущем, преобразование DAO в Singleton позволит установить основу для этого.

Давайте преобразуем OfficeDAO в Singleton:

public class OfficeDAO implements PropertyChangeListener { 

    private static volatile OfficeDAO INSTANCE; 

    private OfficeDAO() { 
     if (INSTANCE != null) {// prevent reflection attacks 
      throw new InstantiationError("Illegal attempt to create more than one instance of OfficeDAO"); 
     } 
     Notification.addChangeListener(this); 
    } 

    public static OfficeDAO getInstance() { 
     OfficeDAO localInstance = INSTANCE; 
     if (INSTANCE == null) { 
      synchronized (OfficeDAO.class) { 
       localInstance = INSTANCE; 
       if (localInstance== null) { 
        INSTANCE = localInstance = new OfficeDAO(); 
       } 
      } 
     } 
     return localInstance; 
    } 

    public void create(Office office) { 
     Connection connection = DBConnection.getConnection(); 

     // ... stuff with the database insertion 

     Notification.notifyDatabaseChanges("ocreate-" + officeId); 
    } 
} 

Если изменить все объекты DAO в Подобным же образом, единственное изменение, которое вы должны сделать в коде клиента изменить ClassName.staticMethod() к ClassName.getInstance().staticMethod().

Пример: OfficeDAO.getInstance().create(..)

* Это, как говорится, это выглядит ваши наблюдатели также субъекты, и это не классический способ, в котором реализован шаблон Observer. Кроме того, вы можете избежать блокировки двойной проверки и прибегнуть к синглтону, который не лениво создается. Как вы реализуете Синглтон, это вопрос вашего выбора, а не напрямую связанный с вопросом.

Если ваш проект начинается с использования инфраструктуры Ioc, такой как Spring или Guice, вы можете избавиться от частного конструктора и метода getInstance. Лучше всего было бы изменить все статические методы в DAO на методы экземпляра и создать структуру IoC и внедрить DAO во все классы, которые их требуют. Это имеет ряд преимуществ:

  1. Большинство каркасов IoC позволяют вам решить, должен ли быть предоставлен только один объект класса по запросу или новые объекты должны предоставляться каждый раз, когда запрашивается один. Поэтому вы можете выбирать между Singleton vs non Singleton DAO без необходимости менять свои DAO.
  2. Ваш источник данных может измениться из базы данных в CSV-файл, и вам не придется менять код клиента, который использует DAO.
  3. Вы можете на самом деле высмеять ваши DAO в классах обслуживания для модульного тестирования.
+1

Ok singleton - это менее взломанное решение, но я бы хотел пойти с «чистым» решением, так как я буду возиться с множеством классов. Что вы подразумеваете под «двойной проверкой блокировки»? Не может ли наблюдатель быть предметом? это анти-шаблон? –

+0

@ sarah.ferguson Количество изменений, которые вы сделаете, обратно пропорционально тому, насколько хакен ваш код. Вы будете возиться с множеством классов с моим решением, но вы не будете сильно меняться в истинном смысле, отличном от того, как клиентский код обращается к методам. Вы можете узнать больше о блокировке двойной проверки [здесь] (http://en.wikipedia.org/wiki/Double-checked_locking). Вам не нужно, чтобы синглтон реализовывался таким образом. Найдите на сайте различные способы реализации Singleton. Нет ничего плохого в том, что наблюдатель является субъектом. – CKing

Смежные вопросы