jayunit100
jayunit100

Reputation: 17648

How can I replace reflection with guice?

I have long used reflection to decouple modules from "handlers".

I have a code base which is architected like this :

static enum AnimalHandlers {
  Dog(Dog.class),
  Cat(Cat.class);

  private final Class c; 

  AnimalHandlers(Class class)
  {
    this.c=class;
  } 

  public Class getAnimalHandler()
  {
    return c;
  }
}

Then later in my code, I have a method which takes an "Animal" enum as input and uses reflection (that is, it gets the class from the enum and invokes "newInstance") to invoke the necessary handler.

I think the solution would be cleaner with Guice. How can I get rid of the enum/reflection and simply use guice to "hydrate" my control module with domain specific logic handlers?

Upvotes: 3

Views: 742

Answers (2)

Gray
Gray

Reputation: 116818

I think that there must be a better pattern here. I'm a little confused as to just how the Animal enum interfaces with the handler but I'll make some general suggestions and maybe one will stick.

  • I assume that there is no way to define the handlers in the Animal enum and you want to decouple the classes. Fine.
  • Could the the handlers register themselves with Animal.setHandler(...)? Then you could just call Animal.Dog.getHandler() to get Dog's handler.
  • I agree with @jfpoilpret that some sort of AnimalHandlerMapper would also be better. I assume there a common interface is possible, even if it just a marker interface.

Code:

private static Map<Animal, AnimalHandler> handlerMap
    = new HashMap<Animal, AnimalHandler>();
static {
    Dog dog = new Dog();
    handlerMap.put(Animal.Dog, dog);
    // we use the same handler twice here
    handlerMap.put(Animal.Wolf, dog);
    handlerMap.put(Animal.Cat, new Cat());
    // do a Animal.values loop at the end to verify that everyone has a handler
}

public static AnimalHandler getHandler(Animal animal) {
    return handlerMap.get(animal);
}
  • If for some reason you can't use the handler instances then I would do the same thing but with handler factories. So you've call handlerMap.get(animal).create(animal) or some such. This would be much cleaner than using reflection.
  • I'm not sure how Guice compares to Spring but if this was spring I would instantiate the handler beans and they would register with the AnimalHandlerMapper to completely decouple it.

Hope this helps.

Upvotes: 2

jfpoilpret
jfpoilpret

Reputation: 10519

You could well use a MapBinder<AnimalEnum, AnimalHandler>, and define a binding for each possible AnimalEnum value.

Upvotes: 2

Related Questions