guiceguice-3

Guice : conditionally instantiate 1 concrete implementation of an interface (among many) at runtime


I am pretty new to Guice and have been trying to see if my problem is solvable with Guice. I have a main Driver class which looks like this :

public class Driver{
  execute(){
    Manager m = injector.getInstance(Manager.class);
  }
}

public class Manager{

  private List<IExecutor> executors;

  @Inject
  public Manager(IExecutorWrapper executor){
    this.executors = executor.getExecutors();
  }

  public List<IExecutor> getExecutors() {
    return executors;
  }

}

My IExecutorWrapper class has multiple implementations, each giving its own list of IExecutors. Only 1 is chosen at runtime, the logic to choose which implementation depends on a context. Whats the best way to design this such that my Driver class doesn't need to change ? How will my GuiceModule look like ?

Thanks !


Solution

  • You can use a custom provider to achieve this, if a Manager is created for every request.

    If Context is injectable (and maybe a request scoped service) :

    @Provides
    IExecutorWrapper createIExecutorWrapper(Context context) {
      if (context.isXX()) {
        return new Executor1();
      } else {
        return new Executor2();
      }
    }
    

    If the implementations of IExecutorWrapper should be injected by Guice, then you can annotated each implementation type, and inject the providers :

    @Provides
    IExecutorWrapper createIExecutorWrapper(Context context, 
           @Type1 Provider<IExecturoWrapper> type1, 
           @Type2 Provider<IExecutorWrapper> type2) {
      if (context.isXXX()) {
        return type1.get();
      } else {
        return type2.get();
      }
    }
    

    and the configuration:

    bind(IExecutorWrapper.class).annotatedWith(Type1.class).to(Executor1.class);
    bind(IExecutorWrapper.class).annotatedWith(Type2.class).to(Executor2.class);