使用DI创建可插入的StrategyFactory

时间:2013-10-11 12:01:34

标签: java dependency-injection strategy-pattern service-locator chain-of-responsibility

我有一个引擎,可以为文本文件处理创建策略。这些文件采用各种格式,引擎通过将文件传递给一系列策略来选择适当的策略,直到其中一个断言它可以解析它。

这不是经典的策略模式。它有点类似于服务定位器模式和责任链模式,并且可以包含其中任何一个方面。

剥离它看起来有点像这样,虽然它目前是用注射创建的:

        public class EngineImpl {

            private Set<Strat> strategies = new HashSet<Strat>();

            public EngineImpl(){
                registerStrategy(new ConcreteStrat1());
                registerStrategy(new ConcreteStrat2());
            }

            public void registerStrategy(Strat strat){
                strategies.add(strat);
            }

            public Strat getStrategy(SomeClass input){
                for (Strat s: strategies)
                    if (s.canParse(input)
                         return s;
                return null;
            }

        }

目前的问题是,EngineImpl必须在编译时知道所有可用的策略才能实现,并且我希望能够在不更改EngineImpl代码的情况下部署新策略。我已经在其他地方寻找过在Java中做这个的选项,并提出空白。我考虑让Strat类在引擎中注册自己,但它们永远不会被类加载器加载,因此永远不会有机会注册。

我可以使用哪些替代方法来注册策略?虽然我目前正在使用DI,但我对其他基于反射和/或注释的解决方案持开放态度。

1 个答案:

答案 0 :(得分:0)

好的,所以现在我想我会做以下事情,虽然远非理想,但至少将其与我的依赖管理的其余部分联系起来。

将一个init方法添加到Strat接口(实现应该自己注册);

public void init(Engine e);

在我的GuiceModule中创建并注入每个Strat,它创建单例并调用注入的方法。

bind(ConcreteStrat1.class).asEagerSingleton();

我希望这种方法有问题可以解决。 Strat对象必须使用@Inject注释它们的init方法,否则它将永远不会被调用。 Eclipse在插入方法存根时会有用地复制它,但是就我所知,它是无法执行的。我不知道这对于“掉入”策略会如何起作用,但我想如果没有更好的东西,我会稍后越过那座桥。

eta:我现在正在编写可以从数据库加载的javascript策略,这使得它可以使用JavascriptStrategyManager轻松插入