听起来您正在寻找MapBinder,这是多重绑定特征。请注意,您仍然需要输入某种IFactory
或其他工厂接口,因为getInstance
不以您的方式获取参数getI
确实如此,您仍然需要建立从整数到类实现的映射某处.
MapBinder风格
class IModule extends AbstractModule {
@Override public void configure() {
MapBinder<Integer, I> myBinder =
MapBinder.newMapBinder(binder(), Integer.class, I.class);
myBinder.addBinding(1).to(A.class);
// Add more here.
}
}
// You can even split the MapBinding across Modules, if you'd like.
class SomeOtherModule extends AbstractModule {
@Override public void configure() {
// MapBinder.newMapBinder does not complain about duplicate bindings
// as long as the keys are different.
MapBinder<Integer, I> myBinder =
MapBinder.newMapBinder(binder(), Integer.class, I.class);
myBinder.addBinding(3).to(C.class);
myBinder.addBinding(4).to(D.class);
}
}
配置有这些模块的注射器将提供可注射的Map<Integer, I>
它有一个所有绑定的实例;这里它将是一个从 1 到完全注入的三条目映射A
实例,从 3 到 aC
实例,从 4 到 aD
实例。这实际上是对您的 switch 示例的改进,该示例使用了new
关键字,因此没有注入任何依赖项A
or B
.
为了获得更好的选择,不会创建这么多浪费的实例,请注入Map<Integer, Provider<I>>
MapBinder 也自动提供。像这样使用它:
class YourConsumer {
@Inject Map<Integer, Provider<I>> iMap;
public void yourMethod(int iIndex) {
// get an I implementor
I i = iMap.get(iIndex).get();
// ...
}
}
不过,为了按照您所做的方式提供“默认”实现(和不透明接口),您需要在MapBinder
map:
class IFactory {
@Inject Map<Integer, Provider<I>> iMap;
@Inject Provider<B> defaultI; // Bound automatically for every Guice key
I getI(int i) {
return iMap.containsKey(i) ? iMap.get(i).get() : defaultI.get();
}
}
更简单,工厂风格
如果上面的内容看起来有些过分,请记住您可以注入一个Injector并创建一个本地Map
从关键到实施。 (您也可以使用ImmutableMap就像我在这里所做的那样)。
class IFactory {
@Inject Injector injector; // This is a bad idea, except for times like this
@Inject Provider<B> defaultI;
static final ImmutableMap<Integer, Class<? extends I>> map = ImmutableMap.of(
1, A.class,
3, C.class,
4, D.class);
I getI(int i) {
return map.containsKey(i)
? injector.getInstance(map.get(i))
: defaultI.get();
}
}