2015-07-11 28 views
0

老實說,我不確定標題是否正確適用;但我會試着用例子來解釋我的問題。java幫助澄清通用類的工廠方法

說我有兩個班

public class Entity { 
    private static int lastID = 0; 
    private int ID; 

    private Entity(){}; 

    public static Entity create(){ 
     lastID++; 

     Entity ent = new Entity(); 
     ent.ID = lastID; 

     return ent; 
    } 
} 

public class Blob extends Entity { 
    private int x,y; 

    pubic void setPos(int X,int Y){; 
     x = X; 
     y = Y; 
    } 
} 

我想與實體工廠接口將在

Blob b = Entity.create<Blob>(); 

形式或自然界的東西的方式。

我最好的嘗試是

public static <E extends Entity> E create(){ 
    E ent = new E(); 
    ... 

但是,這並不想要的工作。

+0

如果你有一個泛型類像'E'你不能用'新E()開始吧' –

+0

我希望Ë將是斑點類 – ZZT

+0

你爲什麼不乾脆用一個別名經典的工廠模式來做你所需要的?您需要將某些參數傳遞給工廠方法,以幫助確定要創建的實體的實例,但 – Constantin

回答

1

恐怕也不能沒有真正傳遞一個類或者它的名字來完成作爲論據。

然後,您可以使用通用構造<E extends Entity<E>>來使其具有類型安全性並避免手動類型轉換。

public class Entity<E extends Entity<E>> { 
    private static int lastID = 0; 
    protected int ID; 

    protected Entity() { 
    } 

    public static <E extends Entity<E>> E create(Class<E> clazz) { 
     lastID++; 

     E newItem; 
     try { 
      newItem = clazz.newInstance(); 
     } catch (InstantiationException | IllegalAccessException e) { 
      throw new RuntimeException(e); // let's hope your child classes will have a working default constructor 
     } 
     newItem.ID = lastID; 
     return newItem; 
    } 

    public int getID() { 
     return ID; 
    } 
} 

public class Blob extends Entity<Blob> { 
    private int x,y; 

    public Blob() { 
    } 

    public void setPos(int X,int Y){; 
     x = X; 
     y = Y; 
    } 
} 

public class AnotherBlob extends Entity<AnotherBlob> { 

    String help = "Help!"; 

    public String help() { 
     return help; 
    } 

} 

// TEST! 
public class Test { 

    public static void main(String[] args) { 
     Blob blob = Entity.create(Blob.class); 
     AnotherBlob anotherBlob = Entity.create(AnotherBlob.class); 

     System.out.println("Blob: " + blob.getClass() + " ID = " + blob.getID() + 
       "\nAnother blob: " + anotherBlob.getClass() + " ID = " + anotherBlob.getID()); 
    } 

} 
+0

這更符合我所尋找的內容。通過這個課是一個無賴,但這是最好的解決方案。非常感謝你,我的朋友。 – ZZT

+0

java中的泛型只是編譯時,所以在運行時JVM將無法確定要實例化的類。這就是爲什麼參數是必需的。 –

+0

您可以從類聲明中刪除'>',並創建一個靜態方法''。上述答案中的測試仍然可行,但編譯器將允許您創建Blob b = Entity.create(ChildOfBlob.class)。如果沒關係,你可以減少泛型雜波。我的答案中的建議不會允許您在Blob上實例化子項。 –

1

一個簡單的工廠方法可能看起來像這樣。把它放在自己的類(而不是在實體類),並有名稱在名廠某處所以它的上下文

public static final Entity getInstance(String id){ 
    Entity instance = null; 
    if(id.equals("Blob")) { 
     instance = new Blob(); 
    } 
    else if(id.equals("Another Blob")) { 
     instance = new AnotherBlob(); 
    } 
    // more Entity types here 
    return instance; 
} 
+0

或者你可以傳遞一個類並檢查'instanceof',就像'getInstance(Class cls)' –

+0

我真的希望避免類的硬編碼生成。它似乎不是一個非常可擴展的方法。 – ZZT

+0

Factory方法的目的是創建一個在編譯時不知道的Entity實例。如果你不喜歡我給出的方法,你也可以使用java.lang.Class.forName(String className)作爲使其更泛化的另一種方式,通過Class參數或類似的方法(直接從Class參數獲取類名稱) – Constantin