4

I've seen at least three ways of acquiring dependencies in a Java object without coupling the object to the creation of the dependency;

Dependency Injection - some framework injects a required object into another object based on an external configuration, example: Spring managed beans

Dependency Lookup - a class looks up a required dependency in some kind of directory service, example: JNDI lookups in a Java EE container

Static Factories - an object in a global scope provides instances on demand - the standard Java SE APIs seem to be littered with these, example: java.util.Logger.getLogger(name), java.util.Calendar.getInstance()

What guidance can you provide as to which is most appropriate for a situation?

brabster
  • 42,504
  • 27
  • 146
  • 186
  • 3
    Just to clarify, Dependency Injection doesn't _require_ a framework and an external configuration, you can write a routine to just create the instances you want and inject them where needed. Of course, if you need to change anything, you will need to recompile (that's where the framework and external config comes in). – Arnold Spence Aug 18 '10 at 19:16
  • I highly recommend searching SO for related questions and answers - this is well-worn territory. For example, see [Dependency Injection & Singleton Design Pattern](http://stackoverflow.com/questions/2662842/dependency-injection-singleton-design-pattern), or visit [ploeh blog](http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx). – Jeff Sternal Aug 18 '10 at 19:36
  • @Jeff Sternal Thanks for the question link, I'd missed that one! – brabster Aug 18 '10 at 19:43

3 Answers3

6

I prefer dependency injection, because the object need not know how it acquires the references it needs.

Dependency lookup still requires the object to know about the lookup service and its URL.

Static factories are similar to lookup services.

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • There's something bugging me, trying to pin it down! This may be a dumb example, but if we use something like log4j, is it appealing/feasible to inject different Logger instances into potentially every class? If not what is different about this use case and is there still a better approach than a static factory? – brabster Aug 18 '10 at 19:40
  • For `log4j`, there isn't really a benefit - you would very rarely ever need to change the logger/name used by a class. Rather, `log4j` is designed in such a way that you configure the named logger to *do different things* based on what you want, i.e. send the output of `com.something.MyClass` logger to a file or database, rather than give `com.something.MyClass` an instance of the file or database logger. – matt b Aug 18 '10 at 19:46
  • It is certainly feasible; that's why a framework like slf4j popped up, which is an adapter for multiple logging frameworks so they can integrate better with containers, spring, etc. – Adriaan Koster Aug 18 '10 at 21:21
  • Isn't logging the classic AOP example? Why would you inject a Logger into every class? – duffymo Aug 19 '10 at 01:07
2

I prefer dependency injection.

When I talk about DI with Spring Framework I see following

  1. It's supported by IDEs (error check, visualization).
  2. You can setup other needed stuff like AOP, properties loading, ...
  3. You have big config possibilities - XML, annotation, JavaConfig
  4. Can be use also in desktop application.

These outbalance every negatives like dependency on another library. Why should I use another approach?

amra
  • 16,125
  • 7
  • 50
  • 47
1

This really depends on the context. If you are writing a self-contained Maths API you might want to use static factories because the code will be less verbose, setup-free and maybe more efficient. If you need to access/provide a remote dependency, a JNDI/LDAP lookup, or ESB messaging would work well. For injecting your services/DAO's/datasources into your typical enterprise server code you'd be better off using one of the common D.I. frameworks like Google Guice or Spring.

There is no single 'best' solution in software design; it's always a tradeoff.

Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60