3

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?

4

1 回答 1

2

AProvider不适用于您的情况,因为正如您所发现的,get()它不采用任何参数。

一种选择是使用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();
  }
}

它没有利用任何令人敬畏的 Guiciness,但它将ActionObject选择逻辑移出ActionHandler,这听起来像是您正在尝试做的事情。注入的映射只是一个Collections.UnmodifiableMap,因此每次调用都会返回相同的实例mappings.get(...),这意味着您的ActionObject实现需要是线程安全的。

另外,我对缺乏main方法的特别关注感到困惑。也许我误解了这个问题,但你可以Injector从任何你想要的地方创建一个 Guice。如果上述解决方案对您不起作用,您可以扩展该限制吗?

于 2012-09-11T01:49:22.320 回答