2013-02-07 59 views
0

我已經0..N對象,每個對象都需要一個唯一的標識符,即以這種方式創建:如何用Java中的工廠替換靜態計數變量?

public class Squirrel { 

    private static numSquirrels = 0; 

    private String id = null; 

    public Squirrel() { 
     this(String.valueOf(numSquirrels++); 
    } 

    public Squirrel(String id) { 
     this.id = id; 
    } 
} 

這是一個問題在幾個方面,但我會給一個:

當單元測試,所述numSquirrels可變攜帶超過 測試之間,即使我可以與不同的羣體的 松鼠中工作。這意味着當我想 喜歡重新開始時,他們的ID會繼續增加。

  • 這是使用SquirrelFactory(那些孩子們正在熱烈討論),正確的時間?
  • 我是否應該使用依賴注入將工廠傳遞給Squirrel對象,還是應該將Squirrel類包含在與外界有接口的Squirrel Factory中?
  • 如果我希望用戶能夠設置ID(或至少提供ID),我該如何確保唯一性?
+0

什麼的目的,從列表中刪除IDS唯一標識符 ? –

+0

當我的對象保存/加載某種文件格式時,這是一項要求。 – sdasdadas

+0

唯一性是有道理的,但我不明白用戶能夠設置ID的重點。 –

回答

3

我認爲這個實現可以正常工作,但是如果你正在處理併發,你應該使用AtomicInteger。

你的單元測試問題可以通過使用嘲笑和包裝在另一個類中來模擬來解決。看到這篇文章 How to mock a static variable in java using JMock

或者,一個簡單的解決方案是暴露一個靜態變量的setter,其中在您的測試用例的結尾,您可以將其設置回0,或任何「重置」意味着您。

+0

這將適用於他,但它不允許檢查ID的唯一性 –

+0

您通常會如何檢查唯一性,爲什麼這不允許它?該setter將被用作清理功能的測試用例 – 75inchpianist

+0

我不確定我是否理解這個答案...我只是添加一個獲取/設置私有靜態變量的方法? – sdasdadas

0

引入一個名爲SquirellPopluation的類,它將充當Squirrel工廠,將靜態計數器移動到它並使其變爲實例變量。

如果你希望工廠的用戶能夠設置自己的ID,那麼使用一個集合而不是一個計數器。

+0

SquirrelPopulation傳遞給Squirrel對象還是使用SquirrelPopulation.createSquirrel()? – sdasdadas

0

您可以爲該類設置靜態「重置」方法。將其稱爲測試的拆除(或設置)的一部分。

+0

我不喜歡爲了重置變量而必須記住呼叫的想法... – sdasdadas

0

松鼠類應該可能不知道工廠。我建議以下實現:

public interface Squirrel // interface, not class 
{ 
    public String getID(); 

    // other methods here 
} 

public class SquirrelFactory 
{ 
    private int nextSquirrelID = 0; 

    public Squirrel createSquirrel() 
    { 
     return new SquirrelImpl (String.valueOf (nextSquirrelID++)); 
    } 

    private static class SquirrelImpl implements Squirrel 
    { 
     private final String id; 

     // other fields here 

     public SquirrelImpl (String id) 
     { 
      this.id = id; 
     } 

     @Overrides 
     public String getID() 
     { 
      return id; 
     } 

     // other methods here 
    } 
} 

然後用SquirrelFactory,而不是構造方法createSquirrel。併爲每個單元測試創​​建SquirrelFactory類的新實例。

0

只是一個具體案件相關的最後一個問題:

如何確保其唯一性,如果我希望用戶能夠設定的ID(或者至少暗示的ID)?

如果你想這樣做,你必須跟蹤所有的實例。例如,您可以使用BitSet。如果你這樣做,你冷提供怎樣的一個解構的:

/** 
* Eat the squirrel.<br> 
* You can not do anything anymore with the squirrel after it has been eaten, 
* but it can be reborn. 
*/ 
public void eat() { //at least, sounds friendlier than kill, shoot, or whatever 
    instances.clear(id); 
} 

要小心,因爲這不是像C++中的真正解構。你不能(很容易)摧毀這個物體。它仍然可以使用。那麼你應該在內部處理這件事。

提示:如果您使用多線程代碼,生活開始變得複雜。但顯然來自靜態ID,你不知道。

0

我認爲爲了滿足您的所有需求,您需要一個SquirrelFactory類來獲得新的ID並確保它們都是唯一的。你可能會想讓SquirrelFactory成爲一個Singleton。

的SquirrelFactory的responsiblities是:IDS的使用

  • 創建基於一個櫃檯一個新的ID松鼠

    • 比方追查(並確保它是唯一的)
    • 創建松鼠與給定ID(用於從文件加載時)以及如果該ID已在使用,則創建如上所示的新
    • 將新松鼠的ID添加到正在使用的ID列表中。
    • 測試你可能想辦法重置計數器和ID列表
    • (可選)有一個方法,當松鼠被刪除