Java工厂模式使用通用约束

时间:2013-04-01 14:58:11

标签: java factory-pattern generic-constraints

我有

public class  MyFactory()
{
   public static <T> T getItem(Element element, Class<T> clazz)
   {
         T item = null;
         if (clazz == IFoo.class)
         {
              item =  (T) new Foo();
         }
         else if (clazz == IBar.class)
         {
              item =  (T) new Bar();
         }
         ...

        assert item instanceof IParsable;
        (IParsable(foo)).parse(element)

       return item;
   }

}

然后我称之为

IFoo parsedFoo = MyFactory.getItem(someElement, IFoo.class);

这里具体的类实现IParsable。我是否能够删除运行时断言检查并进行编译时检查以查看'IParsable'并调用解析?

此外,我想知道是否有办法强制执行IFoo&lt; - &gt; Foo在编译时在getItem()方法中实现关系并删除类型转换(T)

编辑:我想我会给出IFooFoo

的大纲
public interface IFoo
{
    String getFooName();
    int getFooId();
    ....
}


class Foo implements IFoo, IParsable
{
      ...
}

EDIT2:

我只是想到这样的重构,现在唯一不是编译时检查的是接口和实现之间的关系。

  public static <U extends IParsable, T> T getItem(Element element, Class<T> clazz)
   {
         U item = null;
         if (clazz == IFoo.class)
         {
              item =  (U) new Foo();
         }
         else if (clazz == IBar.class)
         {
              item =  (U) new Bar();
         }
         ...

       item.parse(element)

       return (T) item;
   }

3 个答案:

答案 0 :(得分:3)

也许是这样的:

public static <T> T getItem(Element element, Class<T> clazz) {
    IParsable item = null;
    if (clazz == IFoo.class) {
        item = new Foo();
    } else if (clazz == IBar.class) {
        item = new Bar();
    }
    item.parse();
    return (T) item;
}

在编译时检查FooIParsable的事实。另一个演员(到(T))仍然是一个运行时练习 - 但在你的例子中也是如此。

答案 1 :(得分:1)

这里具体的类实现了IParsable。我是否能够删除运行时断言检查并进行编译时检查以查看'IParsable'并调用解析?

From what I know - no, it's not possible. You will be passing object to this method at runtime, the compiler has no idea what objects will be passed. So compile time is not an option here. 

另外我想知道是否有办法强制执行IFoo&lt; - &gt; Foo在getItem()方法的编译时实现关系并删除类型转换(T)?

Again, only at runtime with isAssignableFrom

答案 2 :(得分:1)

你应该在类设置时注册所有的映射(这很难看,因为你不能检查多个具有相同类型参数的边界):

private static Map<Class<?>, Class<?>> MAPPINGS = ...;

static {
  registerMapping(IFoo.class, Foo.class, Foo.class);
  // ...
}

private static <IT, TT extends IT, TP extends IParseable> void registerMapping(Class<IT> ifaceClazz, Class<TT> implClazz, TP parseableClazz) {
  MAPPINGS.put(ifaceClazz, implClazz);
}

然后在getItem()中你的if块变成一个简单的地图查找。请注意,这不会消除(T)演员,但你无能为力。