Вам все еще понадобится MyFactory , чтобы выбрать реализацию, основанную на id
, хотя ваша вспомогательная инъекция может быть очень короткой .
// No need for this to be @Singleton;
// if you want the same shared Foo instance, make it @Singleton
public class MyFactory {
private final B.Factory bFactory;
private final C.Factory cFactory;
@Inject
public MyFactory(B.Factory bFactory, C.Factory cFactory) {
this.bFactory = bFactory;
this.cFactory = cFactory;
}
public A create(final Bar bar) {
switch (bar.getSomeInteger()) { // I assume you're checking a
// property of bar
case 0:
return bFactory.create(bar);
case 1:
return cFactory.create(bar);
//this goes on
}
}
}
public B extends A {
public interface Factory {
B create(Bar bar);
}
private final Foo foo;
public B(final Foo foo, @Assisted final Bar bar) {
super(bar);
this.foo = foo;
}
}
public C extends A {
public interface Factory {
C create(Bar bar);
}
private final Foo foo;
public C(final Foo foo, @Assisted final Bar bar) {
super(bar);
this.foo = foo;
}
}
ИВаш модуль:
public class YourModule extends AbstractModule {
@Override public void configure() {
install(new FactoryModuleBuilder().build(B.Factory.class));
install(new FactoryModuleBuilder().build(C.Factory.class));
}
}
Редактировать: Вы не нуждаетесь в вызове implement
на FactoryModuleBuilder в моем примере, потому что B.Factory
имеет create
метод, который возвращает ваш подкласс B. Если вы хотите, чтобы метод возвращал ваш суперкласс A, скрывая конкретный тип, вы можете сделать это;тогда вам понадобится вызов implement
, потому что Guice не будет знать, какой конструктор попытаться вызвать.
Если вы хотите заставить потребителей кодировать реализацию, вы можете обратиться к фабрике, котораятолько возвращает интерфейс.Как правило, было бы неплохо скрыть детали реализации , и, вероятно, потребуется создать A.Factory
с методом A create(Bar bar)
и связать его с implement
.Однако здесь не нужно , потому что ваш MyFactory уже возвращает A и скрывает подкласс реализации (действующий как A.Factory
с логикой), и потому что вам потребуется @Named
или какая-либо другая аннотация квалификатора, чтобы различатьдве A.Factory
привязки, которые вы создаете.Короче говоря, это дополнительное осложнение, не приносящее пользы в этом конкретном случае.