简体   繁体   中英

IoC and Dependency injection

What's wrong with following code?

public class DeDoper {
    public boolean wackapediaOkToday() {
        DnsResolver resolver =  ResolverFactory.getInstance().makeResolver();
        return resolver.getIpAddressFor("wackapedia.org").equals("123.456.78.9");
    }
}

Why is this version preferred?

public class DeDoper {
    @InjectService
    private DnsResolver resolver;

    public boolean wackapediaOkToday() {
        return resolver.getIpAddressFor("wackapedia.org").equals("123.456.78.9");
    }
}

I can easily mock ResolverFactory.makeResolver() and this is the same as setting resolver is latest example.

This is what was said in this article from ProQuest.biz:

This [first] version of WackapediaOkToday is, very loosely speaking, "injected" with a DnsResolver (although it's admittedly less like getting a shot, and more like asking a waiter for the check). But it does solve the testing problem, and the "turtles all the way down" problem.

Chained to the Factory But in this [first version] approach, we are literally "chained" to the Factory classes. (Worse, if the objects created by our Factories have dependencies in turn, we may have to introduce new Factories inside our Factories.) We haven't fully "inverted" our control, we're still calling (controlling) the Factories from inside our classes.

What was needed was a way to get rid of the control in our classes entirely, and have them told what they were getting (for their dependencies).

Let's say you had a service which can have multiple implementations, like "FileLocator". This has a FilesystemFileLocator, which takes as an argument the path to the root of the files and a S3FileLocator, which takes as an argument your S3 credentials. The former would require you to write a service locator to figure out which version you want and then return it. That code, in turn, has to go get your data, build the appropriate type of file locator, etc. You're doing what the IOC container should do for you. On top of that, you've inject a dependency on that specific creation method.

In the second version you've defined (through annotations or XML) what type of file locator you want. The IOC container instantiates and manages that for you. It's less code you have to maintain. It's also less work if you want to introduce a third type of FileLocator. Or maybe you refactor your code so file locators are singletons, or if they were singletons they're now factories for fresh locators, or maybe you want to pool locator instances. In all these cases there will be less breakage if you work with your IOC container.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM