Reputation: 1123
I have a class that does not have the main method. This class is also used by code that is not in my control. This class has a method that takes a String as a parameter, and then based on the value of that String it needs to create different objects. How can I use Guice to create these objects? I think the answer has something to do with Providers, but I'm not sure how to implement it.
Here is the class in question, which doesn't use DI to make the objects:
public class ActionHandler {
public void doSomething(String message) throws Exception {
ActionObject actionObj = null;
if (message.equals("dog")) {
// ActionObjectDog implements ActionObject
actionObj = new ActionObjectDog();
}
else if (message.equals("cat")) {
// ActionObjectCat implements ActionObject
actionObj = new ActionObjectCat();
}
else {
throw new Exception("Action " + message + " not implemented.");
}
actionObj.run();
}
}
I was trying to inject a Provider, but I got stuck because I couldn't figure out how to make the Provider get() method return a specific implementation of ActionObject.
@Inject private Provider<ActionObject> actionObjectProvider;
Any thoughts?
Upvotes: 3
Views: 705
Reputation: 1178
A Provider
won't work for your situation because, as you have discovered, get()
doesn't take any parameters.
One option is to use a MapBinder
:
class Module extends AbstractModule {
@Override protected void configure() {
MapBinder.newMapBinder(binder(), String.class, ActionObject.class)
.addBinding("dog").to(ActionObjectDog.class);
MapBinder.newMapBinder(binder(), String.class, ActionObject.class)
.addBinding("cat").to(ActionObjectCat.class);
}
}
class ActionHandler {
private final Map<String, ActionObject> mappings;
@Inject ActionHandler(Map<String, ActionObject> mappings) {
this.mappings = mappings;
}
public void doSomething(String message) {
Preconditions.checkNotNull(mappings.get(message), "No action for '" + message + "'")
.run();
}
}
It's not leveraging any awesome Guiciness, but it moves the ActionObject
selection logic out of ActionHandler
, which is what it sounds like you're trying to do. The injected map is just a Collections.UnmodifiableMap
, so the same instance will be returned with each call to mappings.get(...)
, which means your ActionObject
implementations would need to be threadsafe.
Also, I'm confused by the specific attention being paid to the lack of a main
method. Perhaps I'm misunderstanding the problem, but you can create a Guice Injector
from anywhere you'd like. If the above solution doesn't work for you, can you expand on that restriction?
Upvotes: 2