2015-07-11 46 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