Dependency Injection vs Factory Pattern

2019-01-02 19:03发布

Most of the examples quoted for usage of Dependency Injection, we can solve using the factory pattern as well. Looks like when it comes to usage/design the difference between dependency injection and factory is blurred or thin.

Once someone told me that its how you use it that makes a difference!

I once used StructureMap a DI container to solve a problem, later on I redesigned it to work with a simple factory and removed references to StructureMap.

Can anyone tell me what is the difference between them and where to use what, whats the best practice here?

27条回答
旧人旧事旧时光
2楼-- · 2019-01-02 19:29

Theory

There are two important points to consider:

  1. Who creates objects

    • [Factory]: You have to write HOW object should be created. You have separate Factory class which contains creation logic.
    • [Dependency Injection]: In practical cases are done by external frameworks (for example in Java that would be spring/ejb/guice). Injection happens "magically" without explicite creation of new objects
  2. What kind of objects it manages:

    • [Factory]: Usually responsible for creation of stateful objects
    • [Dependency Injections] More likely to create stateless objects

Practical example how to use both factory and dependency injection in single project

  1. What we want to build

Application module for creating order which contains multiple entries called orderline.

  1. Architecture

Let's assume we want to create following layer architecture:

enter image description here

Domain objects may be objects stored inside database. Repository (DAO) helps with retrievar of objects from database. Service provides API to other modules. Alows for operations on order module

  1. Domain Layer and usage of factories

Entities which will be in the database are Order and OrderLine. Order can have multiple OrderLines. Relationship between Order and OrderLine

Now comes important design part. Should modules outside this one create and manage OrderLines on their own? No. Order Line should exist only when you have Order associated with it. It would be best if you could hide internal implementaiton to outside classes.

But how to create Order without knowledge about OrderLines?

Factory

Someone who wants to create new order used OrderFactory (which will hide details about the fact how we create Order).

enter image description here

Thats how it will look inside IDE. Classes outside domain package will use OrderFactory instead of constructor inside Order

  1. Dependency Injection Dependency injection is more commonly used with stateless layers such as repository and service.

OrderRepository and OrderService are managed by dependency injection framework. Repository is responsible for managing CRUD operations on database. Service injects Repository and uses it to save/find correct domain classes.

enter image description here

查看更多
零度萤火
3楼-- · 2019-01-02 19:30

Binoj,

I don't think you have to choose one over the other.

The act of moving a dependent class or interface to a class constructor or setter follows the DI pattern. The object you pass to the constructor or set can be implemented with Factory.

When to use? Use the pattern or patterns that are in your developer wheelhouse. What do they feel the most comfortable with and find easiest to understand.

查看更多
伤终究还是伤i
4楼-- · 2019-01-02 19:30

My thoughts:

Dependecy Injection: pass collaborators as parameters to the constructors. Dependency Injection Framework: a generic and configurable factory to create the objects to pass as parameters to the constructors.

查看更多
十年一品温如言
5楼-- · 2019-01-02 19:30

From a face value they look same

In very simple terms, Factory Pattern, a Creational Pattern helps to create us an object - "Define an interface for creating an object". If we have a key value sort of object pool (e.g. Dictionary), passing the key to the Factory (I am referring to the Simple Factory Pattern) you can resolve the Type. Job done! Dependency Injection Framework (such as Structure Map, Ninject, Unity ...etc) on the other hand seems to be doing the same thing.

But... "Don't reinvent the wheel"

From a architectural perspective its a binding layer and "Don't reinvent the wheel".

For an enterprise grade application, concept of DI is more of a architectural layer which defines dependencies. To simplify this further you can think of this as a separate classlibrary project, which does dependency resolving. The main application depends on this project where Dependency resolver refers to other concrete implementations and to the dependency resolving.

Inaddition to "GetType/Create" from a Factory, most often than not we need more features (ability to use XML to define dependencies, mocking and unit testing etc.). Since you referred to Structure Map, look at the Structure Map feature list. It's clearly more than simply resolving simple object Mapping. Don't reinvent the wheel!

If all you have is a hammer, everything looks like a nail

Depending on your requirements and what type of application you build you need to make a choice. If it has just few projects (may be one or two..) and involves few dependencies, you can pick a simpler approach. It's like using ADO .Net data access over using Entity Framework for a simple 1 or 2 database calls, where introducing EF is an overkill in that scenario.

But for a larger project or if your project gets bigger, I would highly recommend to have a DI layer with a framework and make room to change the DI framework you use (Use a Facade in the Main App (Web App, Web Api, Desktop..etc.).

查看更多
冷夜・残月
6楼-- · 2019-01-02 19:31

IOC is a concept which is implemented by two ways. Dependency creation and dependency injection, Factory/Abstract factory are the example of dependency creation. Dependency injection is constructor, setter and interface. The core of IOC is to not depend upon the concrete classes, but define the abstract of methods(say an Interface/abstract class) and use that abstract to call method of concrete class. Like Factory pattern return the base class or interface. Similariliy dependency injection use base class/interface to set value for objects.

查看更多
皆成旧梦
7楼-- · 2019-01-02 19:32

You can have a look at this link for a comparison of the two (and others) approaches in a real example.

Basically, when requirements change, you end up modifying more code if you use factories instead of DI.

This is also valid with manual DI (i.e. when there isn't an external framework that provides the dependencies to your objects, but you pass them in each constructor).

查看更多
登录 后发表回答