I'm trying to open my mind for fancy IoC principle, and I came across the article: Martin fowler on IoC
He provides some examples of using PicoContainer:
private MutablePicoContainer configureContainer() {
MutablePicoContainer pico = new DefaultPicoContainer();
Parameter[] finderParams = {new ConstantParameter("movies1.txt")};
pico.registerComponentImplementation(MovieFinder.class, ColonMovieFinder.class, finderParams);
pico.registerComponentImplementation(MovieLister.class);
return pico;
}
and then sample usage:
public void testWithPico() {
MutablePicoContainer pico = configureContainer();
MovieLister lister = (MovieLister) pico.g开发者_开发百科etComponentInstance(MovieLister.class);
Movie[] movies = lister.moviesDirectedBy("Sergio Leone");
assertEquals("Once Upon a Time in the West", movies[0].getTitle());
}
And first thought that popped into my head is: why to use something so complicated as PicoContainer to configure creation of an object - and in fact apply Dependency Injection - (I'm .NET developer so in .NET it would probably require using Reflection, which is time consuming), when we can achieve the same encapsulation of object creation in (for instance) Factories or Builder, with fast new operator.
Another thing: configureContainer() is still compiled, exact types are specified at compile time. So why not to use factories, and decide in config file which factory to use?
As I'm new to that approach, I guess there's something I'm missing in terms of benefits of IoC Containers.
I just updated an answer related to this question here.
In .Net I would take a look at the documentation around the Unity Framework (from MSFT). I was also leery of the idea of hard-coding the implementation registrations but over time I got over it. Mainly because you can indeed use file-based configuration, you can register more than one implementation (and tag each one so they can be called upon) and typically you are not using more than one implementation in production anyways.
The biggest benefit is autowiring - where your dependencies are found for you. The chained autowiring of a complex set of classes is very nifty, if nothing else because you can easily register a Mock instance of one of the 10 classes in question without touching the implementation code. This leads to a huge amount of testability at the cost of bootstrapping a container. For me these days, it's table stakes, not even worth the discussion. Imagine if Type1 depends on 2, 3, and 4, 4 depends on 5 and 6, 6 depends on 7. If I want to test how the system reacts to an error in 6, how would I do that? All I need to do is Mock (using a cool framework like Moq) Type6, register the mock, but use real implementations for the other classes.
[Fact]
public void TestType6BlowingUp()
{
IocContainer container = new IocContainer();
container.RegisterType(Type1, Type1Impl);
container.RegisterType(Type2, Type2Impl);
container.RegisterType(Type3, Type3Impl);
container.RegisterType(Type4, Type4Impl);
container.RegisterType(Type5, Type5Impl);
container.RegisterType(Type6, Type6Mock);
container.RegisterType(Type7, Type7Impl);
Type1 type1 = container.Resolve<Type1>();
Type1Response response = type1.DoSomethingThatCallsType6Downstream();
//Should get errorcode 500
Assert.True("Expected ErrorCode 500", response.ErrorCode == 500);
}
精彩评论