Guice 可以根据参数自动创建不同类的实例吗?

2023-11-22

标准对象工厂可能如下所示:

interface I { ... }
class A implements I { ... }
class B implements I { ... }

class IFactory {
    I getI(int i) {
        switch (i) {
        case 1: return new A();
        default: return new B();
        }
    }
}

是否可以设置绑定以便为我完成切换,即我所做的只是调用 getInstance 或注入?我正在研究辅助注射,但这似乎是不同的主题:https://code.google.com/p/google-guice/wiki/AssistedInject


听起来您正在寻找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();
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Guice 可以根据参数自动创建不同类的实例吗? 的相关文章

随机推荐