具有未知实现类的通用工厂 [英] Generic factory with unknown implementation classes

查看:134
本文介绍了具有未知实现类的通用工厂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们假设有两个接口:

  public interface FruitHandler< T extends Fruit> 
{
setFruit(T fruit);
T getFruit();
}

public interface Fruit
{
}

现在我想要一个工厂创建 FruitHandlers (例如 AppleHander OrangeHandler ,...),但是 FruitHandlerFactory 并不知道这两个接口的实现类的必要性(如java参数化泛型静态工厂)。 FruitHandlerFactory 应该以这种方式工作(其中 OrangeHandler 实现 FruitHandler Orange 执行 Fruit ):

  FruitHandlerFactory fhf = new FruitHandlerFactory< OrangeHandler,Orange>(); 
OrangeHandler fh = fhf.create();
橙色橙色=(橙色)fh.getFruit();

这应该是工厂:

  public class FruitHandlerFactory< A extends FruitHandler,B extends Fruit> 
{
public FruitHandler create()
{
FruitHandler< Fruit> fh = new A< B>(); //< ---错误
fh.setFruit(new B());
返回fh;


我得到这个错误:

 类型A不是通用的;它不能用参数< B>来参数化。 

顺便说一下:是否可以使 create() method static?

解决方案

由于Java中的泛型是使用擦除来实现的,所以 FruitHandlerFactory 在运行时不可用,这意味着你不能实例化 A (或者 B

You can ,但传入 Class 对象

  public class FruitHandlerFactory< H extends FruitHandler< F>,F extends Fruit> {
final Class< H> handlerClass;
final Class< F> fruitClass;

public FruitHandlerFactory(final Class< H> handlerClass,final Class< F> fruitClass){
this.handlerClass = handlerClass;
this.fruitClass = fruitClass;
}

public H create()抛出InstantiationException,IllegalAccessException {
H handler = handlerClass.newInstance();
handler.setFruit(fruitClass.newInstance());
返回处理程序;
}
}

一个小缺点是您必须编写类型名称三次(1)如果你想实例化一个 FruitHandlerFactory

  FruitHandlerFactory fhf = new FruitHandlerFactory< OrangeHandler,Orange>(OrangeHandler.class,Orange.class); 

通过产生一个 static createFactory()方法在您的 FruitHandlerFactory

  static< H extends FruitHandler< F>,F extends Fruit> FruitHandlerFactory< H,F> createFactory(
final Class< H> handlerClass,final Class< F> fruitClass){
返回新的FruitHandlerFactory< H,F>(handlerClass,fruitClass);
}

并像这样使用它:

  FruitHandlerFactory fhf = FruitHandlerFactory.createFactory(OrangeHandler.class,Orange.class); 


Let's assume two interfaces:

public interface FruitHandler<T extends Fruit>
{
    setFruit(T fruit);
    T getFruit();
}

public interface Fruit
{
}

Now I want a factory to create FruitHandlers (e.g. AppleHander, OrangeHandler, ...), but the FruitHandlerFactory does not know neccessary about the implementing classes of both interfaces (like in java parameterized generic static factory). The FruitHandlerFactory should work in this way (where OrangeHandler implements FruitHandler and Orange implements Fruit):

FruitHandlerFactory fhf = new FruitHandlerFactory<OrangeHandler,Orange>();
OrangeHandler fh = fhf.create();
Orange orange = (Orange)fh.getFruit();

This should be the factory:

public class FruitHandlerFactory<A extends FruitHandler, B extends Fruit>
{
    public FruitHandler create()
    {
        FruitHandler<Fruit> fh = new A<B>();   //<--- ERROR
        fh.setFruit(new B());
        return fh;
    }
}

Where I get this error:

The type A is not generic; it cannot be parameterized with arguments <B>

BTW: Is it possible to make the create() method static?

解决方案

Since generics in Java are implemented using erasure, the type information of FruitHandlerFactory will not be available at runtime, which means you can't instantiate A (or B) this way.

You can, however pass in a Class object of the correct type to work around this:

public class FruitHandlerFactory<H extends FruitHandler<F>, F extends Fruit> {
    final Class<H> handlerClass;
    final Class<F> fruitClass;

    public FruitHandlerFactory(final Class<H> handlerClass, final Class<F> fruitClass) {
        this.handlerClass = handlerClass;
        this.fruitClass = fruitClass;
    }

    public H create() throws InstantiationException, IllegalAccessException {
        H handler = handlerClass.newInstance();
        handler.setFruit(fruitClass.newInstance());
        return handler;
    }
}

A minor drawback is that you'll have to write the type names three times(1) if you want to instantiate a FruitHandlerFactory:

FruitHandlerFactory fhf = new FruitHandlerFactory<OrangeHandler,Orange>(OrangeHandler.class, Orange.class);

You can somewhat reduce that by producing a static createFactory() method on your FruitHandlerFactory:

static <H extends FruitHandler<F>, F extends Fruit> FruitHandlerFactory<H, F> createFactory(
        final Class<H> handlerClass, final Class<F> fruitClass) {
    return new FruitHandlerFactory<H, F>(handlerClass, fruitClass);
}

and use it like this:

FruitHandlerFactory fhf = FruitHandlerFactory.createFactory(OrangeHandler.class, Orange.class);

这篇关于具有未知实现类的通用工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆