【问题标题】:java parameterized generic static factoryjava参数化通用静态工厂
【发布时间】:2011-05-08 09:57:00
【问题描述】:

是否可以在 Java 中创建使用接口作为参数化类型的静态工厂方法/类并返回给定接口的实现类?

虽然我对泛型的了解有限,但这是我想做的:

// define a base interface:
public interface Tool {
    // nothing here, just the interface.
}

// define a parser tool:
public interface Parser extends Tool {
    public ParseObject parse(InputStream is); 
}

// define a converter tool:
public interface Converter extends Tool {
    public ConvertObject convert(InputStream is, OutputStream os);
}

// define a factory class
public class ToolFactory {
    public static <? extends Tool> getInstance(<? extends Tool> tool) {
       // what I want this method to return is:
       // - ParserImpl class, or
       // - ConverterImpl class
       // according to the specified interface.
       if (tool instanceof Parser) {
          return new ParserImpl();
       }
       if (tool instanceof Converter) {
          return new ConverterImpl();
       }
    }
}

我想限制客户端代码仅将接口“类型”插入从我指定的工具接口扩展的 getInstance() 方法中。这样我就可以确定插入的工具类型是合法的工具。

客户端代码应如下所示:

public class App {
   public void main(String[] args) {

      Parser parser = null;
      Converter converter = null;

      // ask for a parser implementation (without knowing the implementing class)
      parser = ToolFactory.getInstance(parser);

      // ask for a converter implementation
      converter = ToolFactory.getInstance(converter);

      parser.parse(...);
      converter.convert(... , ...);
   }
}

工厂应该打开接口的类型(不管它是否为空),在工厂询问之前定义。我知道这不会像我写的那样工作,但我希望其中一位读者知道我想要完成什么。

getInstance方法的返回类型和传入的参数是一样的,所以在传递一个Parser接口的时候,也会返回一个Parser p = new ParserImpl();返回 p;

提前感谢您帮助我。

【问题讨论】:

    标签: java generics design-patterns factory factory-method


    【解决方案1】:

    有几点:

    1. 您的工厂几乎肯定应该使用一个 来实例化,而不是一个工具对象。让某人创建 Parser 以传递给您的方法以获取 Parser 有点鸡和蛋。
    2. 我不知道是否允许为通配符的方法使用泛型参数;我认为不会,因为这将是荒谬和毫无意义的。当你参数化一个方法时,你需要给泛型参数一个名字,以便你以后可以引用它。

    将这些放在一起,您的工厂方法可能看起来更像这样:

    public static <T extends Tool> T getInstance(Class<T> toolClass) {
       if (Parser.class.isAssignableFrom(toolClass) {
          return new ParserImpl();
       }
       else if (Converter.class.isAssignableFrom(toolClass) {
          return new ConverterImpl();
       }
    
       // You'll always need to have a catch-all case else the compiler will complain
       throw new IllegalArgumentException("Unknown class: " + toolClass.getName());
    }
    

    如果你想将toolClass的类型限制为接口,你不能在编译时这样做,但你当然可以引入运行时检查toolClass.isInterface()

    顺便说一下,这种静态硬编码切换通常不是很。在我看来,将类与构造函数的关系放在Map 中并动态查找构造过程会更好。甚至可以将值存储为 Callable&lt;? extends Tool&gt; 并添加一个受保护的方法,允许其他类注册映射。

    这并不是说您当前的版本不起作用,只是它不能很好地扩展,而且现在我认为它并不能证明拥有一个单独的工厂而不是调用者只是调用 @ 987654328@他们自己。

    【讨论】:

    • 这正是这样做的方式。
    • 感谢您的回答。不知何故,我没有像我想象的那样工作......你能否详细说明客户端代码调用和 Callable建议?我将跳过映射,因为该应用程序只有几个工具并且没有超出这些。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-23
    • 1970-01-01
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    相关资源
    最近更新 更多