Создание подключаемого StrategyFactory с DI
У меня есть движок, который создает стратегии для обработки текстовых файлов. Эти файлы имеют различные форматы, и механизм выбирает подходящую стратегию, передавая файл через цепочку стратегий, пока одна из них не подтвердит, что может его проанализировать.
Это не совсем классическая стратегия. Он чем-то похож на шаблон локатора службы и шаблоны цепочки ответственности и может включать в себя аспекты любого из них.
В разобранном виде это выглядит примерно так, хотя в настоящее время оно создается с помощью инъекций:
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 регистрировались в Engine, но они никогда не загружались загрузчиком классов, и поэтому у меня никогда не было возможности зарегистрироваться.
Какие альтернативные методы я могу использовать для регистрации стратегий? Хотя в настоящее время я использую DI, я открыт для других решений на основе рефлексии и / или аннотаций.
1 ответ
Итак, на данный момент, я думаю, что я собираюсь сделать следующее, которое хотя и далеко от идеала, по крайней мере связывает это с остальной частью моего управления зависимостями.
добавить метод init в интерфейс Strat (реализации должны регистрироваться сами);
public void init(Engine e);
создайте и внедрите каждый слой в мой GuiceModule, который создает синглтон и вызывает внедренный метод.
bind(ConcreteStrat1.class).asEagerSingleton();
Есть проблемы с этим подходом, которые, я надеюсь, могут быть решены. Объекты Strat должны аннотировать свой метод init с помощью @Inject, иначе он никогда не будет вызван. Eclipse старательно копирует это, когда вставляет заглушки метода, но, насколько я могу судить, это невозможно. Я не уверен, как это будет работать со стратегиями "вбрасывания", но, думаю, в отсутствие чего-либо лучшего я перейду этот мост позже.
eta: сейчас я пишу стратегии javascript, которые можно загружать из базы данных, что делает его легко подключаемым с помощью JavascriptStrategyManager