I am using Guice to manager my class dependence. I have a LogicHandler class which depended on several Components class.
public interface LogicHandler {
private Component component1;
private Component component2;
private Component component3;
}
public interface Component {
public String doWork();
}
I will have 3 instances of LoigcHanlder. Using which instance will be decided in run time. Each of instance will have different Component implementation and all implementation are pre-defined.
If I were using spring DI, the xml config would be look like:
<bean id="handler1" class="org.sample.handlers.DefaultHanlder">
<property name="component1" ref="componentImplementationA" />
<property name="component2" ref="componentImplementationB" />
<property name="component3" ref="componentImplementationC" />
</bean>
<bean id="handler2" class="org.sample.handlers.DefaultHanlder">
<property name="component1" ref="componentImplementationD" />
<property name="component2" ref="componentImplementationE" />
<property name="component3" ref="componentImplementationF" />
</bean>
<bean id="handler3" class="org.sample.handlers.DefaultHanlder">
<property name="component1" ref="componentImplementationG" />
<property name="component2" ref="componentImplementationH" />
<property name="component3" ref="componentImplementationI" />
</bean>
Note: all handlers are implemented by DefaultHanlder.
Using which handler instance bases on some parameters.
Assuming I am understanding your question correctly, you would like to pick a particular concrete implementation to bind based on a particular parameter. One way to do this is to create a module that takes as a constructor the parameters you need for deciding which module to bind. The logic to bind the particular concrete implementation would be in the bind
method of the module. E.g
public class YourModule extends AbstractModule {
Parameters settings;
public YourModule(Parameters settings) {
this.settings = settings;
}
@Override
protected void configure() {
if(settings.val == 1) {
bind(DefaultHanlder.class).toInstance(ComponentA.class);
} else if(settings.val == 2) {
bind(DefaultHanlder.class).toInstance(ComponentB.class);
}
.
.
.
}
When you create the injector, use the YourModule
module so that the right wiring is put in place. The injector then should inject the proper concrete class for DefaultHanlder
without your client code knowing how to pick the right concrete implementation.
There are probably other ways to do this as well (e.g. AssistedInjection might also work) but using a separate module is pretty straightforward.