【问题标题】:Java factory pattern using generic constraints使用泛型约束的 Java 工厂模式
【发布时间】:2013-04-01 14:58:10
【问题描述】:

我有

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”并调用解析?

我还想知道是否有办法强制 IFooFoo 在编译时在 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;
   }

【问题讨论】:

    标签: java factory-pattern generic-constraints


    【解决方案1】:

    可能是这样的:

    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))仍然是运行时练习 - 但在您的示例中也是如此。

    【讨论】:

    • 实际上,这永远不会检查 Foo 是否可以转换为 IFoo,因为像这样的通用转换在运行时会被删除。
    • 你想要的是return clazz.cast(item);
    【解决方案2】:

    这里的具体类实现了 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. 
    

    我还想知道是否有办法强制 IFooFoo 在编译时在 getItem() 方法中实现关系并删除类型转换 (T) ?

    Again, only at runtime with isAssignableFrom
    

    【讨论】:

      【解决方案3】:

      您应该像这样在类设置时注册所有映射(这很丑,因为您不能使用相同的类型参数检查多个边界):

      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) 演员表,但您无能为力。

      【讨论】:

      • TT extends IT &amp; IParseable 编译吗?
      • TT extends IT &amp; IParseable 不会编译,我不认为。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多