如何基于某个类实例化特定的实现?

时间:2012-08-24 07:21:22

标签: java reflection interface

我有几个扩展bean的对象:

public class Fruit {}

public class Banana extends Fruit {}

public class Pear extends Fruit {}

我有一个不同实现的接口,每个bean一个。

public interface Milkshake {
    public String doMilkshake();
}

public class FruitMilkshake implements Milkshake {
    public String doMilkshake() {
        return "Fruit Milkshake!";
    }
}

public class BananaMilkshake implements Milkshake {
    public String doMilkshake() {
        return "Banana Milkshake!";
    }
}

public class PearMilkshake implements Milkshake {
    public String doMilkshake() {
        return "Pear Milkshake!";
    }
}

如何根据我的bean的具体类型实例化正确的实现?

现在我使用了典型化,并使用Map来“映射”正确的实现。 像这样:

public void hungry(Fruit fruit) {
    Map<String, String> obj2impl = new HashMap<String, String>();
    obj2impl.put("Fruit", "FruitMilkshake");
    obj2impl.put("Banana", "BananaMilkshake");
    obj2impl.put("Pear", "PearMilkshake");

    String name = fruit.getClass().getCanonicalName();
    String implName = obj2impl.get(name);
    Milkshake milkshake = (Milkshake) Class.forName(implName).newInstance();

    milkshake.doMilkshake(fruit);
}



public interface Milkshake <T t> {
    public String doMilkshake(T t);
}

public class FruitMilkshake implements Milkshake<Fruit> {
    public String doMilkshake(Fruit fruit) {
        return "Fruit Milkshake!";
    }
}

public class BananaMilkshake implements Milkshake<Banana> {
    public String doMilkshake(Banana banana) {
        return "Banana Milkshake!";
    }
}

public class PearMilkshake implements Milkshake<Pear> {
    public String doMilkshake(Pear pear) {
        return "Pear Milkshake!";
    }
}

实现这一目标的更好方法是什么?

2 个答案:

答案 0 :(得分:1)

  

实现这一目标的更好方法是什么?

一个出发点是避免反思课程的名称:

Map<String, Class<? extends Milkshake>> obj2impl =
    new HashMap<String, Class<? extends Milkshake>>();
obj2impl.put("Fruit", FruitMilkshake.class);
obj2impl.put("Banana", BananaMilkshake.class);

...

Milkshake milkshake = obj2impl.get(text).newInstance();

现在仍需要在每个实现中都有一个无参数构造函数,而始终仍会创建一个新实例。如果你使用类似Provider的概念,你可以解决这个问题:

Map<String, Provider<Milkshake>> map = ...;
// Fill the map with providers, some of which could create a new instance,
// and some could reuse an existing one

...

Milkshake milkshake = map.get(text).get();

编辑:重新阅读帖子后,您也可以删除文本部分,并拥有Map<Class<?>, Provider<Milkshake>>。如果可能,请避免对类的名称进行硬编码。

当然,如果你的Fruit班级有一个makeMilkshake抽象方法,那就更好了......

答案 1 :(得分:0)

public class Fruit {
    public Class<? extends Milkshake> getMilkshakeClass() {
        return Milkshake.class;
    }
}

public class Banana extends Fruit {
    public Class<? extends Milkshake> getMilkshakeClass() {
        return Banana.class;
    }
}

public class Pear extends Fruit {
    public Class<? extends Milkshake> getMilkshakeClass() {
        return PearMilkshake.class;
    }
}

你甚至可能想要创建一个AbstractFruit类,它将上面使用的方法作为一个必须覆盖的抽象方法

public abstract class AbstractFruit {
    public abstract Class<? extends Milkshake> getMilkshakeClass();
}

而不是让他们扩展Fruit,扩展它。