Реализация параметризованной фабрики с Guice - PullRequest
6 голосов
/ 16 июня 2011

У меня есть фабрика, которую я хотел бы переопределить с помощью 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 (параметр) и использование привязок для определения, какой объект должен использоваться в каждом случае?

Ответы [ 2 ]

6 голосов
/ 16 июня 2011

У вас есть несколько вариантов здесь.

1. , так как вы используете enum для различения реализаций, тогда у вас есть конечное число реализаций, которые вы можете определить с помощью ихсобственная привязка, при условии, что вы используете аннотацию во время инъекции

public @interface SomeInterfaceKind {
    MyObjects value();
}

в вашем Module:

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

Затем в классы для инъекции:

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

Здесь вы должны определить класс SomeInterfaceKindImpl, который реализует SomeInterfaceKind (да, можно расширить аннотацию!). Для получения более подробной информации, посмотрите, как Named реализован в Guice.

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);
    ...
}
4 голосов
/ 05 августа 2011

Вы также можете использовать вспомогательный ввод

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;
...