2009-11-28 40 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%的時間我從中學到初級保持一個後向參照,這是爲了方便,關係的生命週期已經確定。

...否則,我用的圖表。