2009-11-28 26 views
3

我有一个java模型,其中的类具有应该在两个方向上工作的关联(从1到1,从1到n,从n到n)。在我的java模型中管理双向关联

例子: 类A有B类

B的所有实例都必须知道,谁是他们的父母(A)是一个集合。如果我改变了B的父属性,那么关联也需要在另一侧更新。

我认为,编写代码,使两端的关联保持最新状态是非常繁琐和错误的。

所以:有没有更好的方法来做到这一点?有没有一个Java库可以管理两个对象之间的双向关联?

+1

“我觉得,写代码,即保持了联想最新的两端是相当繁琐且容易出错。”你为什么这么说?这通常不是很困难。 – 2009-11-28 21:52:19

+0

单调乏味,因为我必须为我的所有模型类添加相同的功能。我觉得这是相当复杂的工作。 容易出错,因为我必须保持一些特殊情况记在心里。例如。如果我将B的父项设置为A的另一个实例(将B从一个A转移到另一个实例)会发生什么情况。我必须确保旧链接被删除。但是如果我第二次设置同一个父母怎么办?然后代码不应该触摸已经存在的链接。等 当然这不是不可能得到它的权利,但如果已经有这个问题的解决方案,我为什么要推倒重来? – Damian 2009-11-29 12:55:20

回答

1

你有三个选择:

  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。就我个人而言,我倾向于回避这种方法,因为您可能很容易陷入太多“魔法”的境地,这可能会让人困惑,而且会成为调试的噩梦。

5

另一种方法是将关系移出相关对象。很多时候,A和B都不需要彼此了解;这是使用代码来发现这些属性方便。这是图形或双向地图可以发挥作用的地方。

双向映射可以平凡地用于跟踪一对一的关系。图表可以更好地跟踪其他类型的基数(多对一,多对多等)。

有几个不同的图形实现可以帮助达到此目的。我听说过,但从来没有使用过JGraphT,有一个我使用过很多叫做丛(与国际奥委会容器无关)。分别为http://jgrapht.sourceforge.net/http://plexus.sf.net/

一个图很好,因为它允许完全灵活地定义不同的关系,并且隐式地维护双向链接。

双方关系需要保持同步的事实常常表明关系本身对端点同等重要,而不是双方应该试图封装的东西。

不过,如果父母和孩子真的需要彼此操作,然后一种方法是找出哪些是主要的,是否所有的操作可以通过该对象完成。因此,例如,在父母子女关系中,可以在父母上完成子操作,父母在该操作期间将引用传递给子女。我认为,如果你不能,那么这是一个很好的指标,需要在设计中重新绘制一些线条。

再次使用亲子例子,我还没有真正发现那里的父 - >儿童和儿童安全>家长的关系是如此的动力,一端无法控制它的情况。 99%的时间我从中学到初级保持一个后向参照,这是为了方便,关系的生命周期已经确定。

...否则,我用的图表。