0

我有几个扩展 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!";
    }
}

更好的方法来实现这一目标?

4

2 回答 2

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抽象方法,那就更好了……

于 2012-08-24T07:25:33.237 回答
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,不如扩展它。

于 2012-08-24T07:29:39.227 回答