使用 Guice 实现参数化工厂

发布于 2024-11-16 06:43:57 字数 466 浏览 2 评论 0原文

我有一个工厂,我喜欢使用 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();
    ...
    }
  }

有一个简单的方法来实现它吗? 像 Provider.get(parameter) 之类的东西并使用绑定来定义每种情况下应使用哪个对象?

I have a factory I like to reimplement using 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();
    ...
    }
  }

Is there an easy way to implement it?
Something like Provider.get(parameter) and using bindings to define which object should be used in each case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

2024-11-23 06:43:57

您在这里有多种选择。

1. 由于您使用 enum 来区分实现,因此您拥有有限数量的实现,您可以使用自己的绑定来定义每个实现,前提是您在执行过程中使用注释 在您的 Module 中注入

public @interface SomeInterfaceKind {
    MyObjects value();
}

bind(SomeInterface.class)
    .annotatedWith(new SomeInterfaceKindImpl(MyObjects1.OBJECT1)
    .to(Object1.class);
...

然后在要注入的类中:

@Inject void setSomeInterface(
    @SomeInterfaceKind(MyObjects.OBJECT1) SomeInterface object) {...}

在这里您必须定义实现 SomeInterfaceKindSomeInterfaceKindImpl 类(是的,可以扩展一个注解!)有关更多详细信息,请查看 Guice 中如何实现 Named

2. 您还可以使用 Guice 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);

然后在注入的方法中:

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

You have several options here.

1. since you use an enum to distinguish between implementations, then you have a finite number of implementations that you can define each with their own binding, provided you use an annotation during injection

public @interface SomeInterfaceKind {
    MyObjects value();
}

in your Module:

bind(SomeInterface.class)
    .annotatedWith(new SomeInterfaceKindImpl(MyObjects1.OBJECT1)
    .to(Object1.class);
...

Then in classes to be injected:

@Inject void setSomeInterface(
    @SomeInterfaceKind(MyObjects.OBJECT1) SomeInterface object) {...}

Here you have to define SomeInterfaceKindImpl class that implements SomeInterfaceKind (yes, it's possible to extend an annotation!) For more details, take a look at how Named is implemented in Guice.

2. You can also use Guice MapBinder as follows (I find it simpler to implement)

In your Module:

MapBinder.newMapBinder(MyObjects.class, SomeInterface.class)
    .addBinding(MyObjects.OBJECT1).to(Object1.class);
MapBinder.newMapBinder(MyObjects.class, SomeInterface.class)
    .addBinding(MyObjects.OBJECT2).to(Object2.class);

Then in injected methods:

@Inject void setSomeInterface(Map<MyObjects, SomeInterface> map) {
    SomeInterface object1 = map.get(MyObjects.OBJECT1);
    ...
}
停顿的约定 2024-11-23 06:43:57

使用辅助注入

public interface Factory {

    public Object1 createObject1(String param1);
    public Object2 createObject2(Date param2);

}


public class Object1 {
     @AssistedInject
     public Object1(String param1) {
          // do something
     }
}

public class Object2 {
     @AssistedInject
     public Object2(Dateparam2) {
         // do something
     }
}

您还可以在模块中

install(new FactoryModuleBuilder()
     .implement(Object1.class, Object1.class)
     .implement(Object2.class, Object2.class)
     .build(Factory.class));

然后然后您可以在任何需要的地方使用工厂

@Inject
private Factory factory;

You can also use assisted inject

public interface Factory {

    public Object1 createObject1(String param1);
    public Object2 createObject2(Date param2);

}


public class Object1 {
     @AssistedInject
     public Object1(String param1) {
          // do something
     }
}

public class Object2 {
     @AssistedInject
     public Object2(Dateparam2) {
         // do something
     }
}

Then in your module

install(new FactoryModuleBuilder()
     .implement(Object1.class, Object1.class)
     .implement(Object2.class, Object2.class)
     .build(Factory.class));

Then you can use the factory wherever you need it

@Inject
private Factory factory;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文