В чем фактическая разница между локатором службы и внедрением зависимостей?

Я просматривал предыдущее обсуждение, в котором подробно обсуждалась разница между локатором сервисов и инжектором зависимостей, но все же я не могу этого понять. Могу ли я получить общий ответ без кода?


person Community    schedule 28.08.2012    source источник
comment
comment
Связано: stackoverflow.com/questions/4985455/   -  person Steven    schedule 28.08.2012
comment
Я делал то же самое, но это только усугубляло мое замешательство.   -  person    schedule 28.08.2012


Ответы (2)


В этом примере кода применяется принцип внедрения зависимостей:

public class UserService : IUserService
{
    private IUserRepository repository;

    // Constructor taking dependencies
    public UserService(IUserRepository repository)
    {
        this.repository = repository;
    }
}

В этом примере кода используется шаблон Service Locator:

public class UserService : IUserService
{
    private IUserRepository repository;

    public UserService()
    {
        this.repository = ObjectFactory.GetInstance<IUserRepository>();
    }
}

А это реализация шаблона Service Locator:

public class UserService : IUserService
{
    private IUserRepository repository;

    public UserService(Container container)
    {
        this.repository = container.GetInstance<IUserRepository>();
    }
}

И даже это реализация паттерна Service Locator:

public class UserService : IUserService
{
    private IUserRepository repository;

    public UserService(IServiceLocator locator)
    {
        this.repository = locator.GetInstance<IUserRepository>();
    }
}

Разница в том, что с внедрением зависимостей вы внедряете все зависимости, которые нужны потребителю, в потребителя (но ничего больше). Идеальный способ внедрения — через конструктор.

С помощью Service Locator вы запрашиваете зависимости из некоторого общего источника. В первом примере это был статический класс ObjectFactory, а во втором — экземпляр Container, внедренный в конструктор. Последний фрагмент кода по-прежнему является реализацией шаблона Service Locator, хотя сам контейнер внедряется с использованием внедрения зависимостей.

Есть важные причины, по которым вам следует использовать Dependency Injection вместо Service Locator. Эта статья хорошо объясняет это.

person Steven    schedule 28.08.2012

Если вы используете локатор службы, это обычно означает, что вы явно просите какой-либо объект создать для вас другой объект, что обычно считается антишаблоном. Внедрение зависимостей происходит наоборот.

Скажем, у вас есть класс Воин, у которого есть Оружие. Используя локатор службы, вы запросите у локатора службы оружие в конструкторе Warrior.
Используя внедрение зависимостей, оружие будет внедрено в конструктор Warrior без явного запроса.

person Stefan Billiet    schedule 28.08.2012
comment
Спасибо, это действительно объясняет, и теперь я могу очень хорошо получить все эти примеры. - person ; 29.08.2012
comment
Можете ли вы помочь мне объяснить то же самое с помощью этого примера msdn msdn.microsoft.com/ en-us/library/dd458879.aspx - person ; 29.08.2012
comment
Если класс A зависит от ServiceA и ServiceB, я бы создал конструктор для класса A как таковой: A(ServiceA serviceA, ServiceB serviceB); это внедрение зависимостей (точнее, внедрение конструктора). Используя локатор службы, вы можете создать конструктор без параметров и в этом конструкторе запросить у локатора службы экземпляр ServiceA и экземпляр ServiceB. - person Stefan Billiet; 29.08.2012
comment
Хорошо, и это очень хорошо меня объясняет. - person ; 29.08.2012