Vamos abordar os fundamentos de Injeção de Dependência com uma breve revisão do princípio de injeção de dependência
When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are inverted (i.e. reversed), thus rendering high-level modules independent of the low-level module implementation details. The principle states
- High-level modules should not depend on low-level modules. Both should depend on abstractions.
- Abstractions should not depend on details. Details should depend on abstractions.
Parece que as duas primeiras abordagens que você mencionou podem não estar seguindo totalmente os princípios de DI, porque os objetos de maior ordem parecem precisar saber que tipo de Context
eles deveriam ter.
E antes de continuar, devo admitir um preconceito que potencialmente ofenda os proponentes fanáticos da DI:
DI can get over-emphasized and zealous adherence to the principles can get in the way of writing maintainable code that's appropriate for the environment that it operates within. And that's not necessarily a dig against DI, but rather against any technique that ends up being blindly applied. I'm not saying that you are blindly applying DI, but there are many who fall into that category.
Spoiler usado para proteger aqueles que são excessivamente sensíveis a tais reivindicações
Portanto, antes de chamar os métodos 1 e amp; 2 "ruim", precisamos perguntar se eles estão atendendo às suas necessidades atuais. Essas abordagens envolvem alguma medida de código clichê que é copiado por aí. Isso pode ser bom se você não encontrar a necessidade de alterar esse modelo com frequência.
Da mesma forma, se os objetos puderem usar um e somente um tipo de Contexto, então você não precisará precisar de se preocupar com DI neste caso, pois não há necessariamente algo a o objeto. "Mas e o teste?" é a réplica habitual a essa afirmação pragmática, que é respondida com uma resposta igualmente pragmática de "Esses objetos podem usar / precisam de um contexto diferente para serem testados?" Se sim, use DI. Se não, então ... continue.
A terceira opção que você propõe deixa você mais longe do código clichê e aproxima você de uma abordagem DI. Sua hesitação parece ser:
but I'm not sure how to ensure that everything is using the correct child injector
Acho que a solução para esse desafio é envolver sua criação de Contexto em uma Fábrica e absolver os objetos de maior ordem de saber o que eles precisam chamar.
Então, se eu entendi seu exemplo de código corretamente, em vez disso:
Bar bar = fooChildOne.getInstance(Bar.class);
você teria algo como:
Bar bar = new Bar(ContextFactory.getInstance(Bar.class));
Na sugestão, estamos passando o Contexto retornado do construtor ContextFactory
into Bar
. Pode ser 1 trivial para simplificar o exemplo com:
public class Bar(){
Bar(){
return Bar(ContextFactory.getInstance(Bar.class));
}
}
ou:
public class Bar(){
Bar(){
this.Context = ContextFactory.getInstance(Bar.class);
}
}
1 Meu Java está enferrujado, então eu não sei se você pode encadear construtores como o primeiro exemplo.
E você poderia aumentar um pouco as coisas usando reflexão dentro de ContextFactory
para determinar o Contexto correto para Bar
ou, opcionalmente, passar parâmetros adicionais para o ContextFactory
if Bar
pode manipular vários tipos de Contexto em operação regular.
TL; DR
Use a terceira opção que você propôs e envolva a criação de Contexto em uma Fábrica .