是否可以在 Java 中创建一个使用接口(interface)作为参数化类型的静态工厂方法/类,并返回该给定接口(interface)的实现类?
虽然我对泛型的了解有限,但我想做的是:
// 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();
}
}
}
我想限制客户端代码仅将接口(interface)“类型”插入到从我指定的工具接口(interface)扩展的 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(... , ...);
}
}
工厂应该打开接口(interface)的类型(不管它是否为空),在工厂询问之前定义。我知道这不会像我写的那样起作用,但我希望其中一位读者知道我想要完成什么。
getInstance方法的返回类型与传入的参数相同,所以在传递一个Parser接口(interface)时,也返回一个Parser p = new ParserImpl();返回 p;
在此先感谢您对我的帮助。
最佳答案
一些事情:
- 您的工厂几乎肯定应该采用类 来实例化,而不是工具对象。让某人创建一个
Parser
以传递到您的方法中以获得Parser
有点鸡与蛋。 - 我不知道是否允许您使用通配符方法的通用参数;我想不会,因为这将是荒谬且毫无意义的。当您对方法进行参数化时,您需要为通用参数指定一个名称,以便您稍后可以引用它。
将这些放在一起,您的工厂方法可能看起来更像这样:
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
的类型为接口(interface),编译时是做不到的,当然可以引入运行时检查 toolClass.isInterface()
。
顺便说一句,这种静态的硬编码切换通常不是很好。在我看来,将类到构造函数的关系放在 Map
中并动态查找构造过程会更好。甚至可以将该值存储为 Callable<? extends Tool>
并添加一个 protected 方法以允许其他类注册映射。
这并不是说您当前的版本不起作用,只是它不能很好地扩展,现在我不认为它可以证明拥有一个单独的工厂而不是调用者简单地调用 toolClass.newInstance()
是合理的他们自己。
关于java 参数化泛型静态工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4153767/