Как я могу подключить N цепочек узлов, как фильтры
Я хочу создать узел A(мультиплексор), который имеет N узлов B. Каждый узел B имеет свой собственный узел C, и каждый узел C имеет свой собственный узел D, а каждый узел D имеет свой собственный узел E.
Допустим, N=4 для числа цепей B,C,D,E, которые имеет A. В идеале каждый узел E заканчивается информацией, такой как i=0, 1, 2, 3.
Кроме того, я могу захотеть переупорядочить B, C, D, так как они в значительной степени похожи на фильтры, поэтому у меня все они реализуют интерфейс с
Response service(Request r);
Я отчаянно хотел бы держаться подальше от вспомогательной инъекции, поскольку начинающие разработчики всегда смущаются этим (по крайней мере, я снова и снова замечал это и устал учить этому, и я тоже думаю, что это немного уродливо и запутанно). Кажется, они не нуждаются в обучении всем остальным вещам, что делает его легким.
Я думаю, может быть, я просто внедряю провайдера, а у B есть C, у C есть D, а затем у всех есть методы запуска, но такого рода не получилось, как я надеялся, так как метод запуска должен меняться в каждой службе и все их методы запуска должны совпадать. Видите, проблема в том, что Узел A имеет информацию о том, что такое номер узла E, и должен получить эту информацию для E, но B, C и D не нуждаются в этой информации.
Я мог бы сделать некоторую проводку в конструкторе А и иметь
Provider<B> bProvider
Provider<E> eProvider
но потом, как мне получить E до конца. Я не совсем уверен в чистом способе сделать все это.
спасибо, Дин
1 ответ
Я могу придумать три способа сделать это: детские инъекторы, ручной DI и вспомогательная инъекция.
Детские инъекторы
Это, вероятно, лучший вариант, также указанный в моем ответе два года назад.
Пользуясь подсказкой из документации Guice о "проблеме с ногами робота", вы можете создать детский инжектор, который позволит @NodeNumber int
привязка в любом месте вашего дерева, что вы хотите. Это означает, что ваши привязки и структура не должны сильно меняться, даже если меняется порядок фильтров или если ваш номер узла позже понадобится в C, D, F или любой их зависимости. B, C, D, E не будет инъецируемым, пока вы не предоставите привязку NodeNumber, но это, вероятно, правильно для того, что вы описываете.
Естественно, вы могли бы использовать @Named("nodeNumber")
вместо определения @NodeNumber
обязательная аннотация, или вы можете сделать рефакторинг в BFactory, который вы сохраните в другом месте.
class E {
@Inject @NodeNumber int nodeNumber; // Available anywhere in your graph!
}
class D { @Inject E e; }
class C { @Inject D d; }
class B { @Inject C c; }
class A {
@Inject Injector injector; // You can always inject the Injector!
B addNode(final int nodeNumber) {
// Create a new injector
return injector.createChildInjector(new AbstractModule() {
@Override public void configure() {
bindConstant().annotatedWith(NodeNumber.class).to(nodeNumber);
}
}).getInstance(B.class);
}
}
Ручной DI
Если у вас есть только несколько зависимостей, которые изменяются нечасто, вы можете создать свой собственный стек вручную. Это может не использовать Guice в полной мере, но совершенно ясно, что здесь происходит, и что нужно изменить, если B/C/D/E получат или потеряют какие-либо провалы.
class A {
@Inject Provider<SomeDepOfB> bDep; // If anything in the tree has other deps,
@Inject Provider<SomeDepOfC> cDep; // you'll need to provide them yourself.
@Inject Provider<SomeDepOfD> dDep;
B addNode(int nextNodeNumber) {
return new B(
bDep.get(),
new C(
cDep.get(),
new D(
dDep.get(),
new E(nextNodeNumber))));
}
}
Вспомогательная инъекция
Вы сказали, что пытаетесь избежать этого, но я приведу это здесь для полноты.
class E {
interface Factory { E create(int nodeNumber); }
E(@Assisted int nodeNumber, SomeDep1OfE dep1, SomeDep2OfE dep2) { /* ... */ }
}
class D {
interface Factory { D create(int nodeNumber); }
D(@Assisted int nodeNumber, E.Factory eFactory) { /* ... */ }
}
// ...
class YourModule extends AbstractModule {
@Override public void configure() {
install(new FactoryModuleBuilder().build(E.Factory.class)); // Binds E.Factory
}
}
Хотя вспомогательный впрыск не может быть правильным выбором, его использование довольно простое и может отнять много пробной массы (особенно, если у E много других дел и т. Д.).