Управление двунаправленными ассоциациями в моей модели Java - PullRequest
3 голосов
/ 29 ноября 2009

У меня есть Java-модель, в которой у классов есть ассоциации (от 1 до 1, от 1 до n, от n до n), которые должны работать в обоих направлениях.

Пример: класс A имеет коллекцию класса B

Все экземпляры B должны знать, кто их родитель (A). Если я изменю родительское свойство B, связь должна быть обновлена ​​и на другой стороне.

Я думаю, что написание кода, который поддерживает ассоциации на обоих концах, довольно утомительно и подвержено ошибкам.

Итак: есть ли лучший способ сделать это? Существует ли библиотека Java, которая может управлять двунаправленными ассоциациями между двумя объектами?

Ответы [ 2 ]

5 голосов
/ 29 ноября 2009

Другой подход заключается в перемещении отношений из рассматриваемых объектов. Много раз ни А, ни В никогда не должны знать друг о друге; это использование кода, который находит эти свойства удобными. Именно здесь могут вступать в игру графики или двунаправленные карты.

Двунаправленные карты можно легко использовать для отслеживания отношений один к одному. Графики могут быть намного лучше в отслеживании других типов кардинальности (многие-к-одному, многие-ко-многим и т. Д.)

Существует несколько различных реализаций графа, которые могут помочь в этом. Я слышал, но никогда не использовал JGraphT, и есть один, который я часто использовал, это plexus (никакого отношения к контейнеру IOC). http://jgrapht.sourceforge.net/ и http://plexus.sf.net/ соответственно.

График хорош, потому что он обеспечивает полную гибкость в определении различных отношений, а двунаправленная связь поддерживается неявно.

Тот факт, что обеим сторонам отношений необходимо синхронизироваться, часто является признаком того, что сами отношения имеют одинаковую важность для конечных точек, а не то, что каждая сторона должна пытаться инкапсулировать.

Тем не менее, если родитель и потомок действительно do должны работать друг с другом, то один из подходов состоит в том, чтобы выяснить, что является первичным и можно ли все операции выполнять через этот объект. Так, например, в родительских дочерних отношениях могут быть выполнены дочерние операции над родителем, когда родитель передает ссылку на себя дочерним элементам во время этой операции. Я бы сказал, что если вы не можете, то это хороший показатель того, что некоторые линии необходимо перерисовать в дизайне.

Снова используя пример parent-child, я действительно не нашел случая, когда отношения parent-> child и child-> parent были настолько динамичны, что один конец не мог их контролировать. И в 99% случаев я держу обратную ссылку от вторичной к первичной, это для удобства и жизненный цикл отношений хорошо установлен.

... в противном случае я использую график.

1 голос
/ 29 ноября 2009

У вас есть три варианта:

  1. Управляйте обоими сторонами этой ассоциации;
  2. Сделать это эффективно двунаправленным. Под этим я подразумеваю, что это однонаправлено, но это фактически другой путь через код; или
  3. Аспектно-ориентированное программирование.

В качестве примера 2 у вас есть отношения один-ко-многим между Домом и комнатой. Номер имеет ссылку на дом. Вы можете вести список комнат в доме или сделать что-то вроде:

public class House {
  ...

  public List<Room> getRooms() {
    List<Room> ret = new ArrayList<Room>();
    for (Room room : /* list of ALL rooms */) {
      if (room.getHouse().equals(this)) {
        ret.add(room);
      }
    }
    return ret;
  }
}

Могут быть обстоятельства, когда достижение производительности в этом случае оправдано.

С помощью (3) вы можете использовать аспектно-ориентированное программирование (например, Spring AOP, AspectJ), чтобы создать точку на установке House on Room для автоматического обновления House. Лично я склонен уклоняться от этого подхода, так как вы легко можете оказаться в ситуации, когда слишком много «магии», которая может сбить с толку и кошмар для отладки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...