Difference between Dependency Injection and Factory Pattern in Java

TL;DR Main difference between dependency injection and factory pattern is that in the case of former dependency is provided by the third party (framework or container) while in the case of later dependency is acquired by client class itself. Another key difference between them is that use of dependency injection result in loosely coupled design but the use of factory pattern create a tight coupling between factory and classes which are dependent on the product created by the factory. Though both Dependency Injection and Factory pattern look similar in a sense that both creates an instance of a class, and also promotes interface driven programming rather than hard coding implementation class; But, there are some subtle differences between Factory pattern and dependency injection pattern.

In the case of factory design pattern, client class is responsible for calling getInstance() of factory class to create an instance of products, it also means that client class is directly coupled with factory and can't be unit tested without factory class being available.

On the other hand in Dependency Injection, client class has no clue about how his dependencies are created and managed. It only knows about dependencies. Mostly dependencies are injected by framework e.g. bean class exists without any hard-coded dependency, as those are injected by IOC container e.g. Spring.

If you are serious about learning design patterns and principles, I suggest you take a look at Head First Object Oriented Analysis and design book. This book is overshadowed by its popular cousin Head First Design Pattern but it's one of the books to master object-oriented design principles and patterns.

Factory Pattern vs Dependency Injection in Java

You can also use points discussed here to answer questions like difference between Spring IOC and Factory pattern because Spring IOC is nothing but an implementation of dependency injection pattern.

Factory Pattern vs Dependency Injection

To understand difference between factory pattern and dependency injection better let's see examples of how both DI and Factory design pattern are used :


In Factory Pattern

public class CashRegister {

    private PriceCalculator calculator = PriceCalculatorFactory.getInstance();

    public void add(Transaction tx) {
          int price = calcualtor.getPrice(tx);
          add(price);
    }

}

In this case dependent class, CashRegister is directly coupled with PriceCalculatorFactory because its calling static getInstance() method from PriceCalculatorFactory to satisfy its dependency. In order to test CashRegister, you must need a PriceCalculatorFactory, which is not good for unit testing of this class.

On the other hand, if you use Dependency injection, then dependencies are added by framework e.g. Spring framework or DI container like Google Guice because you reverse the responsibility of acquiring dependencies.

Now it's the responsibility of IOC container to inject dependency than the dependent class fending for himself. In the case of dependency injection any class just looks like a POJO.

In Dependency Injection 

public class CashRegister {

    private PriceCalculator calculator;

    public CashRegister(PriceCalculator calculator){
        this.calculator = calculator;
    }

    public void add(Transaction tx) {
          int price = calcualtor.getPrice(tx);
          add(price);
    }

    public void setCalcuator(PriceCalculator calc){
        this.calculator = calc;
    }

}

You can see that dependency for CashRegister, which is PriceCalculator is supplied via a constructor, this is known as constructor dependency injection. There is another form of DI as well e.g. setter injection, in which dependency is provided using setter method.

For example, setCalcuator(PriceCalcuator) is facilitating setter injection there. You should use constructor injection to inject mandatory dependencies and setter injection for optional, good to have dependencies. You can also see when to use Setter vs Constructor injection for more guidelines.

Dependency injection vs Factory design pattern


Difference between Factory Pattern vs Dependency Injection

Based on our knowledge of both of these patterns, you can easily deduce following key differences between them :


1) Factory pattern adds coupling between object, factory, and dependency. Object not only needs a dependent object to work properly but also a Factory object. While in case of dependency injection, Object just knows the dependency, it doesn't know anything about container or factory


2) As compared to Factory pattern, Dependency injection makes unit testing easier. If you use the factory pattern, you need to create the object you want to test, the factory and the dependent object, of course, you factor can return a mock object, but you need all this just to start with unit testing. On the other hand, if you use dependency injection, you just need to mock the dependency and inject into an object you want to test, no clutter or boilerplate is needed.


3) Dependency injection is more flexible than factory pattern. You can even switch to different DI framework e.g. Spring IOC or Google Guice.


4) One of the drawbacks of Dependency injection as compared to Factory pattern is that you need a container and configuration to inject the dependency, which is not required if you use factory design pattern.

In true sense, it's not such a bad thing because you have one place to see dependency of your class and you can control them, but yes when you compare DI to a factory method, this is the additional step you need to do.


5) Due to low coupling, DI results in much cleaner co than factory pattern. Your object looks like POJO and you also come to know what is mandatory and what is an option by looking which type of dependency injection your class is using.

If an object is injected using Setter injection, which means it's optional and can be injected at any time, while dependencies which are injected using constructor injection means they are mandatory and must be supplied in the order they are declared.


6) Another tricky scenario with using DI is creating an object with too many dependencies and worse if those are injected using constructor injection. That code becomes difficult to read. One solution to that problem is to use Facade pattern and inject dependencies by encapsulating in another object. For example, you can introduce an object say ApplicationSettings which can contain DBSetting, FileSetting and other configuration settings required by an object.


7) You should use Dependency Injection Patterns to introduce loose coupling. Use Factory Patterns if you need to delegate the creation of objects. In short, dependency injection frees your application from factory pattern boilerplate code. All the work which is required to implement a factory is already done by IOC containers like Spring and Google Guice.


That's all between the difference between Factory design pattern and dependency injection in Java. Both patterns take out the creation of dependencies from the dependent class and encourage the use of interfaces for defining property e.g. here we are using PriceCalculator which is an interface so that it can later be replaced by any suitable implementation without affecting any part of code.


The real difference between factory and dependency injection lies on the fact that in the case of a factory, your dependent class is still dependent on factory, which is a new form of dependency while DI takes out the dependency completely. This means dependency injection provides better decoupling and unit testing of classes over Factory design pattern.

Difference between Factory pattern and dependency injection
If you like this article and interested in learning more about design patterns and principles, you may like following ones as well :
  • What is the difference between Adapter, Decorator, and Proxy design patterns? (answer)
  • How to implement Builder design Pattern in Java? (solution)
  • 10 Object Oriented Design Principle Every Programmer Should know (principles)
  • What is Open Closed design Principle in OOP? (answer)
  • What is the difference between Factory and Abstract Factory design Patterns? (answer)
  • 5 Reasons to use Composition in place of Inheritance in Java? (answer)
  • How to implement Strategy Design Pattern using Java Enum? (solution)
  • What is the difference between State and Strategy Pattern in Java? (answer)
  • Top 5 Books to Learn Design Patterns and Principles (books)
  • How to implement DAO design Pattern in Java? (answer)
  • Why implementing Singleton using Enum is better than Class in Java? (answer)
  • What is the difference between Association, Aggregation, and Composition in OOP? (answer)
  • What is the difference between Singleton and Static Class in Java? (answer)
  • Why should you Interface for Coding in Java? (answer)
  • Real life example of Decorator Pattern in Java? (example)

Recommended books for further reading on design patterns for Java developers 

  • Head First Design Pattern by Kathy Sierra (check here)
  • Refactoring, Improving design of existing code (check here)


7 comments :

Elvis Donald Attro said...

Hi Javin . That's a good article . You've make everything clear.
+1 for mentioning Head First's OOAD. I'm starting my journey to Object Oriented Design and I'm glad this book was the first I've picked . It's just goldmine and I don't even understand why it looks so less popular.
Now that you've made things clear between DI and Factory, the difference between DI and Strategy is now blurry!
Can you please try to give us more light on this ?
Thanks

mateusduboli said...

Great Post!

But I would like to make some remarks.

A FW it's not needed to achieve DI, it helps a lot, yes, but DI can be achieved without it.

DI is about removing the responsibility of controlling the class dependencies from it, so that the dependent class it's not responsible for the creation or retrieval of it's dependencies.

I couldn't think of scenarios were a "optional" dependency was useful, could you exemplify that?

When the need to create a facade in order to join many dependencies appears, I can argue that the class is doing too much. I understand using this when talking about utility objects, such as loggers and settings, but it seems like a anti-pattern.

Regards,

Javin Paul said...

@Elivs Donald Atro, thanks for your comment. Indeed Head First's OOAD is one of the fantastic book for Java developer struggling to understand true essence of Object Oriented programming. It often get unnoticed due to Head First design pattern, another great book. Sure, we'll write about difference between dependency injection and strategy pattern sooner.

Javin Paul said...

@mateusduboli, Yes, in true sense you can always write code to create, maintain and inject dependencies but as you said a framework like Spring IOC and Google Guice helps a lot.

There are many places where optional dependencies are useful e.g. Car class without Audio system, without camera to record anything etc. You can still have a functional car without those accessories.

Regarding your last point, true , but it mostly depends upon context, if its just settings or config parameters then its ok but if its more than that e.g. doing logical thing like reporting, parsing, saving etc then yes, time to refactor your class into multiples.

Elvis Donald Attro said...

A whole blog post. That's will be so cool !
Thanks

SARAL SAXENA said...

@Javin I would suggest to keep the concepts plain and simple. Dependency Injection is more of a architectural pattern for loosely coupling software components. Factory pattern is just one way to separate the responsibility of creating objects of other classes to another entity. Factory pattern can be called as a tool to implement DI. Dependency injection can be implemented in many ways like DI using constructors, using mapping xml files etc

Unknown said...

Thanks a lot, good article.
I wonder, why there is only a shy little reference in 4) about the overhead of container configuration ?
Maybe because, unlike factory, the configuration can not be tested (because it is not a code), so the user has to deploy and run the application to make sure all instances can be created without exceptions in constructors and/or in container?

Post a Comment