问题在于你的代码中有些部分使用了泛型,而其他部分则没有。你可以采用不安全的方式,从一个方法返回不同类型的称重器。然而,这样做会失去使用泛型时得到的类型安全性。例如:
Plant banana = ...
Plant spinach = ...
Weigher<Plant> bananaWeigher = WeigherFactory.getInstance(banana)
bananaWeigher.weigh(spinach)
另一种方法是使WeigherFactory针对每个具体的
Plant
类具有不同的方法,并使使用
WeigherFactory
的代码也具有通用性。例如:
public class WeigherFactory {
public static BananaWeigher getInstance(Banana banana) {
return new BananaWeigher();
}
public static SpinachWeigher getInstance(Spinach spinach) {
return new SpinachWeigher();
}
}
public abstract class FactoryUser<P extends Plant> {
public abstract Weigher<P> getWeigher(P plant);
public void run(P plant) {
Weigher<P> weigher = getWeigher(plant);
int weight = weigher.weigh(plant);
System.out.println("the plant weighs: " + weight);
}
}
public class Main {
public static void main(String[] args) {
Banana banana = new Banana();
FactoryUser<Banana> factoryUser = new FactoryUser<Banana>() {
@Override
public BananaWeigher getWeigher(Banana banana) {
return WeigherFactory.getInstance(banana);
}
};
factoryUser.run(banana);
}
}
当你不知道植物的实际类型时(访问者模式)
我们需要一个PlantWeigher
来称量所有类型的Plant
。如果需要,它可以委托给专门的称量器。但是我们需要一个中央称量器,因为您将无法返回特定的称量器并以类型安全的方式使用它。中央称量器将使用访问者模式来分派每种植物的正确称量方法。
首先,您需要一个Visitor
接口和该类的实现,该实现知道如何处理每个具体的植物类。例如:
public interface Visitor<T> {
public T visit(Banana banana);
public T visit(Spinach spinach);
}
public class WeighingVisitor implements Visitor<Integer> {
@Override
public Integer visit(Banana banana) {
return banana.getBananaWeight();
}
@Override
public Integer visit(Spinach spinach) {
return spinach.getSpinachWeight();
}
}
public class PlantWeigher {
public int weigh(Plant plant) {
return plant.accept(new WeighingVisitor());
}
}
其次,您需要修改
Plant
基类以定义一个抽象方法,该方法接受一个
Visitor
。只有
Plant
的具体实现需要实现此方法。
public interface Plant {
public <T> T accept(Visitor<T> visitor);
}
public class Banana implements Fruit {
private int weight;
public Banana(int weight) {
this.weight = weight;
}
public int getBananaWeight() {
return weight;
}
@Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
}
最后,如何使用所有这些:
List<Plant> plants = asList(new Banana(10), new Spinach(20));
PlantWeigher weigher = new PlantWeigher();
int weight = 0;
for (Plant p : plants) {
weight += weigher.weigh(p);
}
System.out.println("total weight: " + weight);