Tuesday, September 12, 2023

Difference between Dependency Injection and Factory Design Pattern in Java with Example

Learning a Programming language like Java or Python is easy, but writing production-quality code is difficult. Coding is as much art as the science behind it. To write good code, you need to carefully design your classes, their dependency, and how to use that. This is important so that it can survive the constant change throughout his lifetime. If you have been coding for some time, then you know that SOLID principles and Design Patterns help you to write better code. This is obvious because they are proven the solution to some common problems software developers face all around the world. But, knowing just the design pattern is not enough, you also need to learn to use the right design pattern in the right place.

In this article, we are going to look at two design patterns, the Factory pattern and Dependency Injection, and learn the difference between them so that you can develop the coding sense for their effective use.

Btw, if you are here to know the answer of dependency injection vs. factory pattern then let me tell you that the 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 the use of dependency injection results in loosely coupled design, but the use of factory patterns creates a tight coupling between factories and classes which are dependent on the product produced by the factory.

Btw, If you are serious about learning design patterns and principles, I suggest you take a look at the Design Patterns in Java course on Udemy.  This course covers both SOLID design principles like Open Closed and Liskov substitution, and all-important Object Oriented design patterns like Decorator, Observer, Chain of Responsibility, and much more.





Factory Pattern vs. Dependency Injection in Java

Though both Dependency Injection and Factory pattern look similar in the sense that both creates an instance of a class, and also promotes interface-driven programming rather than hard-coding implementation class,  there are some subtle differences between the Factory pattern and Dependency injection pattern, which we'll discuss next.

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

On the other hand, in Dependency Injection, the client class has no clue about how his dependencies are created and managed. It only knows about dependencies.

Most dependencies are injected by a framework like a bean class exists without any hard-coded dependency, as those are injected by IOC container like Spring Framework.

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

If you want to learn more about how exactly dependency injection works in Spring, I suggest you join a comprehensive Spring course like Spring Framework 5: Beginner to Guru by John Thompson on Udemy. It is also the most up-to-date and covers Spring 5 and Reactive programming.

Dependency Injection and Factory Design Pattern in Java Spring





Dependency Injection vs. Factory Pattern in Code

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

1. Factory Pattern Code Example

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 it's calling the static getInstance() method from the PriceCalculatorFactory to satisfy its dependency. 

In order to test the CashRegister class, you must need a PriceCalculatorFactory, which is not suitable for unit testing of this class and makes unit testing harder. 

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

Now it's the responsibility of the 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.

2. Dependency Injection Code Example 

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 a setter method.

For example, the 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.

If you want to learn more about Setter vs. Constructor Injection, particularly from the Spring Framework point of view, which supports both of them, I suggest you take a look at the Spring Master Class - Beginner to Expert course. Another great course to learn and master Spring online by yourself.


Dependency Injection vs Factory Design Pattern in Java Spring





Difference between Factory Pattern vs. Dependency Injection

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

1) The factory pattern adds coupling between objects, factories, 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 the 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 it into an object you want to test, no clutter or boilerplate is required.


3) Dependency injection is more flexible than the factory pattern. You can even switch to different DI frameworks like Spring IOC or Google Guice.


4) One of the drawbacks of Dependency injection, as compared to the Factory pattern, is that you need a container and configuration to inject the dependency, which is not required if you use a factory design pattern.
In a real sense, it's not such a bad thing because you have one place to see the 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 a much cleaner co than the factory pattern. Your object looks like POJO, and you also come to know what is mandatory and what is an option by looking at 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 that 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 the Facade pattern and inject dependencies by encapsulating it in another object.  For example, you can introduce an object say ApplicationSettings, which can contain DatabaseSetting, FileSetting, and other configuration settings required by an object. You can read more about Facade patterns in the Design Pattern Library course on Pluralsight, which is one of the best collections of design patterns in one place.




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.

And, here is an excellent summary of some key differences between the Factory Pattern and Dependency Injection pattern in Java and OOP:


Difference between Factory pattern and dependency injection


That's all about the difference between a 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 a 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 the code.

The real difference between factory and dependency injection lies in the fact that in the case of a factory, your dependent class is still reliant on a 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 the Factory design pattern.


Further Learning
Design Pattern Library
Web Application Architecture 101
Java Design Patterns - The Complete Masterclass


If you like this article and interested in learning more about design patterns and principles, you may like the following ones as well :
  • 5 Free Courses to learn Object Oriented Programming (courses)
  • My favorite courses to learn Software Architecture (courses)
  • What is the difference between Adapter, Decorator, and Proxy design patterns? (answer)
  • How to implement the Builder design pattern in Java? (solution)
  • 10 Object-Oriented Design Principle Every Programmer Should know (principles)
  • What is the 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 the Strategy Design Pattern using Java Enum? (solution)
  • What is the difference between State and Strategy patterns 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)
  • A real-life example of the Decorator Pattern in Java? (example)
  • 5 Online Courses to learn Design Pattern in Java (courses)
  • 10 Courses to Learn Microservices with Spring and Java (courses)

Thanks for reading this article so far. If you like this article about the Factory design pattern vs Dependency Injection pattern in Java, then please share it with your friends and colleagues. If you have any questions or feedback, then please drop a note.

P. S. - If you are keen to learn about Design Patterns and Software architecture and looking for a free online training course to start with then you can also check out Java Design Patterns and Architecture course on Udemy. It's completely free and all you need is a free Udemy account to join this course.

8 comments:

  1. 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

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

      Delete
  2. 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,

    ReplyDelete
  3. @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.

    ReplyDelete
  4. @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.

    ReplyDelete
  5. @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

    ReplyDelete
  6. 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?

    ReplyDelete