如何通过CDI实现命令模式?

时间:2013-11-22 18:54:54

标签: java java-ee design-patterns dependency-injection

我是CDI的新手,有点困惑。我有以下问题。我们有课程动作。我们有包装类,它将所有Action对象保存在hashmap中。这样的事情。

class TestAction implements Action{
  @EJB
  private MyBean bean; 
  public void doSomething(){
    //here we do something with injected EJB
  }
}

class Foo {
   private HashMap<String, Action> hm;
   public void execute (String action){
   this.hm.get(action).doSomething();    
 }    
}

当我不使用CDI时 - 一切正常。但我需要使用它。因此,据我所知,我必须通过cdi容器创建所有操作,否则CDI容器无法将托管bean注入其中。所以我的问题是什么是通过CDI实现命令模式的最佳方法?

编辑: 我阅读了Dhanji R. Prasanna的依赖注入,Weld-reference(WR),JavaEE7教程(CDI部分) - 不建议阅读最后一篇。在思考了一点之后,我明白我需要注入HashMap。此外,我明白我必须使用生产者方法。好。我说。终于我明白了。所以我编写了以下生成器方法:

@ApplicationScoped
public class ActionMapFactory {
    @Produces @Preffered
    public HashMap<String, Action> getHashMap(){
    HashMap<String, Action> hm=new HashMap<>();
     if (...){
     hm.put("save",new SaveAction());
     }
     return hm;
    }
}

来自WR:

  

上面的代码有一个潜在的问题。实施   使用Java new运算符实例化。对象   由应用程序直接实例化无法利用   依赖注入,没有拦截器。

我已经阅读了WR的解决方案,但是如果我有很多动作和很多Foo的子类,我该怎么办?

1 个答案:

答案 0 :(得分:1)

您可以通过将所有操作注入new并在生产者方法中填充ActionMapFactory来避免HashMap

@ApplicationScoped
public class ActionMapFactory {

    @Inject
    private SaveAction saveAction;

    @Inject
    private DeleteAction deleteAction;

    // And so on

    @Produces @Preffered
    public HashMap<String, Action> getHashMap() {
        Map<String, Action> hm = new HashMap<>();
        hm.put("save", saveAction);
        hm.put("delete", deleteAction);
        return hm;
    }
}

如果您不想将这些Action实例保留为属性,请执行构造函数注入:

private Map<String, Action> actionMap;

// This is part of the CDI bean contract
protected ActionMapFactory() {}

@Inject
public ActionMapFactory(SaveAction saveAction, DeleteAction deleteAction) {
    actionMap = new HashMap<>();
    actionMap.put("save", saveAction);
    actionMap.put("delete", deleteAction);
}

@Produces @Preffered
public HashMap<String, Action> getHashMap() {
    return actionMap;
}