在我的guice模块中,我有多个工厂,如下图所示。
install(new FactoryModuleBuilder().implement(SportsCar.class,Ferrari.class).build(FerrariFactory.class));
install(new FactoryModuleBuilder().implement(LuxuryCar.class,Mercedes.class).build(MercedesFactory.class));
这两个工厂都有下面的create方法,它需要一个assisted元素。
Ferrari create(@Assisted Element partsElement);
Mercedes create(@Assisted Element partsElement);
在CarChooser类中,我得到了Ferrari或Mercedes的实例,如下图所示。
@Inject
public CarChooser(FerrariFactory ferrariFactory , MercedesFactory mercedesFactory )
{
this.ferrariFactory = ferrariFactory;
this.mercedesFactory = mercedesFactory;
}
在同一个类里
if(type.equals("ferrari"))
ferrariFactory.create(partsElement);
else if (type.equals("mercedes"))
mercedesFactory.create(partsElement);
...
现在,什么 我试图让这个CarChooser类的扩展是开放的,但修改是封闭的,也就是说,如果我需要添加另一个工厂,我不应该把它声明为一个变量+添加到构造函数中+为相应的新类型添加另一个if子句。 我打算在这里使用ServiceLoader,并声明一个接口CarFactory,这个接口将由所有工厂(如FerrariFactory、MercedesFactory等)实现,所有实现都有一个getCarType方法。但我如何使用Service Loader调用创建方法?
ServiceLoader<CarFactory> impl = ServiceLoader.load(CarFactory.class);
for (CarFactory fac: impl) {
if (type.equals(fac.getCarType()))
fac.create(partsElement);
}
}
是正确的方法,如果它的工作(我甚至不知道这是否会工作)。或者有什么更好的方法来做同样的事情吗?
感谢帖子中的第一个评论,我知道我想使用MapBinder 。我写了一个CarFactory,它是由FerrariFactory和MercedesFactory扩展。所以我添加了以下内容。
MapBinder<String, CarFactory> mapbinder = MapBinder.newMapBinder(binder(), String.class, CarFactory.class);
mapbinder.addBinding("Ferrari").to(FerrariFactory.class);
mapbinder.addBinding("Mercedes").to(MercedesFactory.class);
但是由于上面代码的.to部分是抽象类,我得到一个初始化错误说FerrariFactory没有绑定到任何实现上。我在这里应该有什么来将它绑定到用 FactoryModuleBuilder 声明的正确的 Assisted Inject Factory ?
所以,使用MapBinder与generics一起使用就是解决方案。
install(new FactoryModuleBuilder().implement(SportsCar.class,Ferrari.class).build(FerrariFactory.class));
install(new FactoryModuleBuilder().implement(LuxuryCar.class,Mercedes.class).build(MercedesFactory.class));
MapBinder<String, CarFactory<?>> mapbinder = MapBinder.newMapBinder(binder(), new TypeLiteral<String>(){}, new TypeLiteral<CarFactory<?>>(){});
mapbinder.addBinding("ferrari").to(FerrariFactory.class);
mapbinder.addBinding("mercedes").to(MercedesFactory.class);
这里需要注意的是,这似乎只在Guice 3.0+JDK 7中支持。对于JDK 8,你需要Guice 4.0 ! 在以下网站上发现了这个问题 https:/github.comgoogleguiceissues904。
希望能帮到你。
更多关于解决方案的细节。
http:/crusaderpyro.blogspot.sg201607google-guice-how-use-mapbinder.html。