Search code examples
javaguice

Conditionally instantiating classes that use @Inject


I'm trying to understand how to handle conditionally creating new instances of a class that uses @Inject. In the below example I have a factory that instantiates classes based on a parameter.

AnimalFactory does not have access to the injector the main class of my application has, so I can't use injector.getInstance(Cat.class)

class AnimalFactory {

    public IAnimal create(AnimalType type) {
        if (type.equals(AnimalType.CAT)) {
            return new Cat(); // Cat uses @Inject, so this won't work of course. But ???
        } else if (type.equals(AnimalType.DOG)) {
            return new Dog(); 
        }
    }
}

In the rest of my app, classes are injected into my constructors because I always need them. Guice creates an instance/singleton for each. But in this scenario, I do not want to create and inject instances for each animal because all but one are needed.


Solution

  • You can use a MapBinder as described here:

    public class AnimalModule extends AbstractModule {
      public void configure() {
        MapBinder<AnimalType, IAnimal> animalBinder= MapBinder.newMapBinder(binder(), AnimalType.class, IAnimal.class);
    
        animalBinder.addBinding(AnimalType.DOG).to(Dog.class);
         ...
      }
    }
    

    And than use it in your factory:

    class AnimalFactory {
       @Inject
       Map<AnimalType, IAnimal> animals;
    
       public IAnimal create(AnimalType type) {
           return animals.get(type);
       }
     }