2011-09-20 35 views
10

我正在用Java設計一個遊戲引擎。Java:執行雙向鏈接對象

該引擎的核心存在兩個類Asset和Attribute,其中Asset包含一個Attributes列表。大多數屬性不需要鏈接備份到其屬性,這意味着屬性可以並經常出現在多個資產的列表中。但是,有一個名爲UniqueAttribute的屬性的擴展,它是針對那些特定於其資產的實現,並利用鏈接返回。

  1. 理想的情況下,我的資產的addAttribute方法會是這個樣子,如果我切出的其他代碼:

    public void addAttribute(Attribute attribute){ 
        if(attribute instanceof UniqueAttribute) 
        ((UniqueAttribute)attribute).setAsset(this); 
        attributeList.add(attribute); 
    } 
    

    不幸的是,因爲他們生活在不同的包,UniqueAttribute.setAsset()必須是public 。這使得該方法對引擎的外部用戶開放以致於混亂,而我可以通過直接使用這種方法來手工關閉它,這是一個錯誤 - 它似乎相當sl。。

  2. 第二個選項是提供UniqueAttribute與建設的資產,這意味着在創建點的代碼看起來是這樣的:

    asset.addAttribute(new UniqueAttribute(asset)); 
    

    雖然我可以添加一個檢查 - 和 - 可投擲或斷言來確認正確的資產通過,我基本上依靠用戶來連接這兩個,我也不願意這樣做。

  3. 第三個選項是硬着頭皮,把50 java文件都到同一個軟件包,這樣我就可以使用標準的可視性。

是否有某種模式或什麼的,這將有助於鏈接這兩個在一起不暴露的電線,或迫使我把一切都變成一個巨大的包?

無關緊要的咆哮:我一直不喜歡java中的子包的概念並沒有真正以任何有意義的方式擴展。就Java而言,一個子包只是一個不同的包,並且我已經有很多場合可以使用更多與此直接相關的可見性修飾符。

+0

可能選項2以某種廠是知道的獨特屬性和資產之間的關係? –

+0

雖然我想有可能已經工作了子包的特殊規則,這是幾乎沒有必要(因爲你可以使用系統,如Spring或OSGi的執行接口和實現之間的距離),並會作出的事情非常複雜得多收益不大。簡單可靠的實現比「可愛」但複雜的功能更重要。 –

回答

2

我的建議是Asset,Attribute和UniqueAttribute應該都在同一個包中(可能還有一些其他的核心「引擎」類)。然後,您可以使用UniqueAttribute.setAsset的標準軟件包可見性。

你並不需要把所有其他類在同一個包 - 您Asset.addAttribute方法應當公開,訪問其他包,以便您的應用程序的其他部分可以只使用直接。

因此,解決辦法可以在您的分類被稱爲「3-」。

如一些更基本點,還要考慮:

  • 無論您真正需要的兩個屬性和UniqueAttributes的複雜性 - 我不知道你真的,之前實施了一個相當複雜的遊戲對象模型,而不需要任何看起來像UniqueAttribute的東西。如果UniqueAttribute「需要一個鏈接回」,那麼也許它正試圖太聰明/做太多?
  • 即使你確實需要兩者,你是否真的想編寫代碼來將它們視爲同一對象的一部分?他們看起來在概念上有很大的不同,如果將兩者混淆起來,你最終會編寫大量的條件代碼。
  • 還有其他各種優點,它們一致地共享和不可變 - 對於內存使用情況,併發性和可測試性等等。由於它們可能相當小,因此在需要的情況下,寫入時複製語義的成本是微不足道的。
+0

以前我是用上面的方法之一,因此UniqueAttribute是不是新的 - 我只是在看一些核心的改進。你的觀點二:我覺得我有太多的條件代碼,如果我單獨兩個,是因爲存在在屬性列表迭代特定的一個或類型多點。然而,這是有見地的 - 我會更多地考慮它。 – Numeron

+0

啊我明白你爲什麼要現在的反向鏈接!如果遍歷具有特定屬性的所有對象是問題,那麼您可能需要考慮保留具有重要屬性的所有對象的單獨索引(HashSet可能?)。您可以在添加/刪除對象或更改屬性時更新此設置。雖然你必須保持這個索引同步,但這是有效的,很容易測試,並且避免了在屬性本身中放置複雜邏輯的需要。 – mikera

0

好了,基本上你想要做的三件事情:

  1. 化妝setAsset方法與所有其他包
  2. 不要使用含子包類資產
  3. 隱藏setAsset方法封裝內可見要實現這一點

這是有點問題:如果你聲明公共方法在屬性類所有其他類包括th在包(我們稱之爲AttributePackage),你不能阻止用戶包含某個地方的包。

在另一方面,你可以做到以下幾點:

  1. 創建只包含該用戶應該使用屬性方法的接口,我們稱之爲AttributeInterface
  2. 化妝屬性實現該接口
  3. 添加AttributeInterface到新包

想要使用Attribute類的用戶應該通過AttributeInterface使用它,同時 資產將直接使用Attribute類以訪問所有方法。

我打一個比方:

//attribute interface package 
public interface AttributeInterface{ 
    public void publicAttributeMethodClientShouldUse(); 
} 

//attribute package 
public class Attribute{ 
    public void setAsset(Asset a); 
    public void publicAttributeMethodClientShouldUse(); 
} 

資產將直接引用屬性同時用戶應引用AttributeInterface。希望清楚。

+0

我不確定用戶在這種情況下如何創建一個帶有資產鏈接的屬性?實現接口意味着它只是一個沒有getAsset()訪問權限的標準屬性,並且擴展該類與我在問題中提出的問題相同。 – Numeron

2

我會在屬性添加回調方法,當屬性的一個實例添加到一個資產被稱爲:

class Attribute { 
    protected void addedToAsset(Asset asset) { 
     // do nothing 
    } 
} 

這種方法將在的addAttribute方法被調用

class Asset { 
    public void addAttribute(Attribute attribute) { 
     attributeList.add(attribute); 
     attribute.addedToAsset(this); 
    } 

} 

而且該方法將在UniqueAttribute中被覆蓋以控制與資產的鏈接:

class UniqueAttribute extends Attribute { 
    Asset asset; 
    protected void addedToAsset(Asset asset) { 
     // manage the previous link if needed 
     if (this.asset != null) { ... } 
     this.asset = asset; 
    } 
} 

請看這個解決方案,Asset和Attribute應該放在同一個包中。但UniqueAttribute可以在任何你想要的包中。

1

修改您的scond選項

asset.addAttribute(new UniqueAttribute(asset)); 

這樣的:

class UniqueAttribute { 
Asset asset; 
    public UniqueAttribute(Asset asset) { this.asset = asset; asset.addAttribute(this); } 
} 

做非唯一屬性類似的方法。這意味着不是從外部使用addAttribute(),而只是在構造函數中使用它。

的另一種選擇是在兩個工廠方法添加到資產:createAttribute()和createUniqueAttribute();

+0

這樣UniqueAttribute的資產也可以是最終的,這會減少UniqueAttributes的可變性。 – OliverS

+0

雖然這意味着我有上面的同樣的問題,除了我會與addAttribute而不是setAsset的visiblity爭論。 – Numeron

0

首先,這些實體確實似乎是如此緊密相關以至於被置於相同的包中。我將它們放在同一個包中,並使addAttribute方法包爲私有。

請記住,自從在Java中引入AccessibleObject後,語言中的可見性和訪問控制已經變成了唯一的化妝品......使用您的庫的任何人都可以獲取您的類並使私有方法和字段可訪問和可修改!地獄,他們甚至可以修改final成員!因此,請不要將注意力放在可見性方面,只要確保您的模型和方法流程對您的用戶有意義且正確工作即可。

+0

對不起,我說的是'UniqueAttribute.setAsset()'被製成包的私有方法。 – vagelis