用Guice实现参数化工厂

Gen*_*sky 6 java design-patterns guice

我有一个工厂,我喜欢使用Guice重新实现:

enum MyObjects { OBJECT1, OBJECT2, ... }
class Object1 implements SomeInterface { ... }
class Object2 implements SomeInterface { ... }
...
class Factory {
  public static SomeInterface createObject(MyObjects obj) {
    switch (obj) {
    case OBJECT1: return new Object1();
    case OBJECT2: return new Object2();
    ...
    }
  }
Run Code Online (Sandbox Code Playgroud)

有没有一种简单的方法来实现它?像Provider.get(参数)和使用绑定来定义在每种情况下应该使用哪个对象?

jfp*_*ret 6

你有几个选择.

1.因为您使用a enum来区分实现,那么您可以使用自己的绑定定义有限数量的实现,前提是您在注入期间使用注释

public @interface SomeInterfaceKind {
    MyObjects value();
}
Run Code Online (Sandbox Code Playgroud)

在你的Module:

bind(SomeInterface.class)
    .annotatedWith(new SomeInterfaceKindImpl(MyObjects1.OBJECT1)
    .to(Object1.class);
...
Run Code Online (Sandbox Code Playgroud)

然后在要注入的类中:

@Inject void setSomeInterface(
    @SomeInterfaceKind(MyObjects.OBJECT1) SomeInterface object) {...}
Run Code Online (Sandbox Code Playgroud)

在这里你必须定义SomeInterfaceKindImpl实现的类SomeInterfaceKind(是的,它可以扩展注释!)有关更多细节,请看看如何Named在Guice中实现.

2.您也可以使用吉斯MapBinder如下(我觉得很容易实现)

在您的模块中:

MapBinder.newMapBinder(MyObjects.class, SomeInterface.class)
    .addBinding(MyObjects.OBJECT1).to(Object1.class);
MapBinder.newMapBinder(MyObjects.class, SomeInterface.class)
    .addBinding(MyObjects.OBJECT2).to(Object2.class);
Run Code Online (Sandbox Code Playgroud)

然后在注入的方法:

@Inject void setSomeInterface(Map<MyObjects, SomeInterface> map) {
    SomeInterface object1 = map.get(MyObjects.OBJECT1);
    ...
}
Run Code Online (Sandbox Code Playgroud)