Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency inversion. Object creation

According to SOLID principles a class cannot depend on other classes, dependencies have to be injected. It's simple:

class Foo
{
    public Foo(IBar bar)
    {
        this.bar = bar;
    }

    private IBar bar;
}

interface IBar 
{
}

class Bar: IBar 
{
}

But what if I want my Foo class to be able to create Bar's, not knowing the exact implementation behind IBar? I can think of 4 solutions here, but all of them seem to have drawbacks:

  1. injecting the type of object and using reflection
  2. using Generics
  3. using "Service Locator" and calling the Resolve() method.
  4. creating a separated factory class and injecting it into Foo:

class Foo
{
    public void DoSmth(IBarCreator barCreator) 
    {
        var newBar = barCreator.CreateBar();
    }
}

interface IBarCreator 
{
    IBar CreateBar();
}

class BarCreator : IBarCreator
{
    public IBar CreateBar()
    {
        return new Bar();
    }
}

Last case seems natural, but BarCreator class has too litle code. So how do you think, which is best?

like image 682
tov.Novoseltsev Avatar asked Aug 26 '11 11:08

tov.Novoseltsev


People also ask

What is an example of dependency inversion principle?

In our example, CustomerBusinessLogic depends on the DataAccess class, so CustomerBusinessLogic is a high-level module and DataAccess is a low-level module. So, as per the first rule of DIP, CustomerBusinessLogic should not depend on the concrete DataAccess class, instead both classes should depend on abstraction.

What is the purpose of dependency inversion principle?

To provide a summary, the Dependency Inversion Principle is primarily about reversing the conventional direction of dependencies from "higher level" components to "lower level" components such that "lower level" components are dependent upon the interfaces owned by the "higher level" components.

How dependency inversion principle is used in agile design methodology?

Definition: One should depend upon abstractions and not concrete instances. Typically in a software application, high level components need to depend on lower level components. If the low level components are 'hard-coded' into the high level components this causes two problems.

Why do we need Dependency Inversion C#?

Benefits of Implementing the Dependency Inversion Principle Our classes are not tightly coupled with the lower-tier objects and we can easily reuse the logic from the high-tier modules. So, the main reason why DIP is so important is the modularity and reusability of the application modules.


2 Answers

I like to "inject" a Func<IBar> in this case. Like so:

class Foo
{
    public Foo(Func<IBar> barCreator)
    {
        this.bar = barCreator();
    }

    private IBar bar;
}

interface IBar 
{
}
like image 65
Random Dev Avatar answered Sep 22 '22 05:09

Random Dev


This is what factories were made for.

If you feel your factory has too little code, ask yourself what benefit it's giving you over just creating the instance inline. If the benefits outweigh the costs of the added code, then don't worry about it.

I'd personally avoid service location, or if you really must use it I'd hide it behind a factory anyway. Service location tends to be easily abused, and can lead to your container finding its way into code it shouldn't have anything to do with.

For convenience, some containers allow you to specify a factory to be used by the container when it creates an instance of a component. In this case, your class could depend on IBar directly but your container would call IBarCreator when it needs a new instance. Castle Windsor has the methods UseFactory and UseFactoryMethod in their API, for example.

like image 43
James Gregory Avatar answered Sep 21 '22 05:09

James Gregory