java参数化通用静态工厂

use*_*342 1 java generics design-patterns factory factory-method

在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();
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

我想限制客户端代码只将接口'type'插入到我指定的Tool接口扩展的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(... , ...);
   }
}
Run Code Online (Sandbox Code Playgroud)

工厂应该在工厂询问之前定义界面的类型(如果它是否为空则不小心).我知道这不会像我写的那样工作,但我希望其中一位读者知道我想要完成的事情.

getInstance方法的返回类型与传入参数相同,因此当传递Parser接口时,它还返回一个Parser p = new ParserImpl(); 返回p;

在此先感谢您的帮助.

And*_*yle 7

有几件事:

  1. 您的工厂几乎肯定会使用来实例化,而不是Tool 对象.有人创建一个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());
}
Run Code Online (Sandbox Code Playgroud)

如果要限制toolClass接口的类型,则不能在编译时执行此操作,但您当然可以引入运行时检查toolClass.isInterface().

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

这并不是说你当前的版本不起作用,只是因为它不能很好地扩展,而且现在我认为它没有做太多证明有一个单独的工厂而不是调用者只是调用toolClass.newInstance()自己.