[Design-Patterns] В чем разница между шаблонами зависимостей зависимостей и шаблонов Locator?


Answers

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

Хорошее сравнение: http://martinfowler.com/articles/injection.html

Если ваш инжектор зависимостей выглядит как локатор службы, где классы напрямую вызывают инжектор, это, вероятно, не инжекторы зависимостей, а скорее локатор сервисов.

Question

Оба шаблона кажутся воплощением принципа инверсии управления. То есть, объект не должен знать, как построить его зависимости.

Инъекция зависимостей (DI), по-видимому, использует конструктор или сеттер для «инъекции» его зависимостей.

Пример использования инжекции конструктора:

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

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

  //...
}

Локатор сервисов, похоже, использует «контейнер», который связывает свои зависимости и дает foo bar.

Пример использования локатора службы:

//Foo Needs an IBar
public class Foo
{
  private IBar bar;

  public Foo()
  {
    this.bar = Container.Get<IBar>();
  }

  //...
}

Поскольку наши зависимости - это только сами объекты, эти зависимости имеют зависимости, которые имеют еще больше зависимостей и т. Д. И т. Д. Таким образом, возникла инверсия контрольного контейнера (или контейнера DI). Примеры: Castle Windsor, Ninject, Structure Map, Spring и т. Д.)

Но контейнер IOC / DI выглядит точно как локатор сервисов. Называет ли это контейнер DI плохим именем? Является ли контейнер IOC / DI только другим типом локатора сервисов? Является ли нюанс тем фактом, что мы используем контейнеры DI в основном, когда у нас много зависимостей?




Я думаю, эти двое работают вместе.

Инъекция зависимостей означает, что вы вставляете некоторый зависимый класс / интерфейс в класс потребления (обычно к его конструктору). Это отделяет два класса через интерфейс и означает, что потребительский класс может работать со многими типами реализаций «внедренной зависимости».

Роль локатора обслуживания заключается в том, чтобы объединить вашу реализацию. Вы устанавливаете локатор сервисов через некоторую загрузочную привязку в начале вашей программы. Bootstrapping - это процесс ассоциирования типа реализации с конкретным абстрактным / интерфейсом. Что создается для вас во время выполнения. (на основе вашего config или bootstrap). Если вы не реализовали инъекцию зависимостей, было бы очень сложно использовать локатор сервисов или контейнер МОК.




Какая разница (если таковая имеется) между Injection Dependency и Service Locator? Оба шаблона хорошо реализуют принцип инверсии зависимостей. Шаблон Locator Service легче использовать в существующей кодовой базе, поскольку он делает общий дизайн более свободным, не вызывая изменений в публичном интерфейсе. По этой же причине код, основанный на шаблоне Locator Service, менее читабельен, чем эквивалентный код, основанный на Injection Dependency.

Образцы зависимостей Injection позволяют понять, с какой подписи будут связаны зависимости, которыми обладает класс (или метод). По этой причине полученный код чище и читабельнее.




Мартин Фаулер утверждает :

С помощью локатора сервисов класс приложения запрашивает его явно сообщением локатору. При инъекции нет явного запроса, служба появляется в классе приложения - следовательно, инверсия элемента управления.

Короче говоря, Service Locator и Dependency Injection - это просто реализация принципа инверсии зависимостей.

Важным принципом является «Зависимость от абстракций, а не от конкреций». Это сделает ваш дизайн программного обеспечения «слабосвязанным», «расширяемым», «гибким».

Вы можете использовать тот, который наилучшим образом соответствует вашим потребностям. Для большого приложения, имеющего огромную базу кода, вам лучше использовать Service Locator, потому что Injection Dependency потребует больше изменений в вашей кодовой базе.

Вы можете проверить это сообщение: Инверсия зависимостей: Локатор сервисов или Инъекция зависимостей

Также классика: инверсия контрольных контейнеров и модель впрыска зависимостей Мартина Фаулера

Проектирование многоразовых классов от Ralph E. Johnson & Brian Foote

Тем не менее, тот, который открыл мне глаза, был: ASP.NET MVC: разрешить или внедрить? Это проблема ... Дино Эспозито




В моем последнем проекте я использую оба. Я использую инъекцию зависимостей для проверки единиц. Я использую локатор службы, чтобы скрыть реализацию и быть зависимым от моего контейнера IoC. и да! Когда вы используете один из контейнеров IoC (Unity, Ninject, Windsor Castle), вы зависите от него. И как только он устарел или по какой-то причине, если вы захотите его поменять, вам, возможно, придется изменить свою реализацию - по крайней мере, составной корень. Но локатор сервиса реферат, что фаза.

Как вы не будете зависеть от своего контейнера IoC? Либо вам придется обернуть его самостоятельно (это плохая идея), либо вы используете Service Locator, сконфигурируйте свой контейнер IoC. Таким образом, вы сообщите локатору службы о том, какой интерфейс вам нужен, и он вызовет контейнер IoC, сконфигурированный для получения этого интерфейса.

В моем случае я использую ServiceLocator который является компонентом структуры. И используйте Unity для контейнера IoC. Если в будущем мне нужно поменять мой контейнер IoC на Ninject все, что мне нужно сделать, - мне нужно настроить локатор сервисов на использование Ninject вместо Unity. Легкая миграция.

Вот замечательная статья объясняет этот сценарий; http://www.johandekoning.nl/index.php/2013/03/03/dont-wrap-your-ioc-container/




Примечание. Я не совсем отвечаю на вопрос. Но я чувствую, что это может быть полезно для новых учеников шаблона Injection Dependency, которые путают его с помощью шаблона Locator (anti-), который случайно наткнулся на эту страницу.

Я знаю разницу между Service Locator (теперь это рассматривается как анти-шаблон) и шаблонами зависимостей зависимостей, и может понять конкретные примеры каждого шаблона, но я был смущен примерами, показывающими локатор службы внутри конструктора (предположим, повторное введение конструктора).

«Локатор сервисов» часто используется как имя шаблона, так и имя для ссылки на объект (предположительно тоже), используемый в этом шаблоне для получения объектов без использования нового оператора. Теперь этот же тип объекта может также использоваться в корне композиции для выполнения инъекции зависимостей, и именно здесь возникает путаница.

Следует отметить, что вы можете использовать объект локатора службы внутри конструктора DI, но вы не используете «шаблон локатора службы». Это менее запутанно, если вместо этого использовать его как контейнерный объект IoC, поскольку вы, возможно, догадались, что они по сути делают то же самое (поправьте меня, если я ошибаюсь).

Независимо от того, упоминается ли он как локатор службы (или только локатор) или как контейнер IoC (или просто контейнер), не имеет никакого значения, как вы предполагаете, поскольку они, вероятно, относятся к одной и той же абстракции (исправьте меня, если я ошибаюсь ). Это просто, что вызов этого локатора сервисов предполагает, что один использует анти-шаблон Service Locator вместе с шаблоном Injection Dependency.

IMHO, назвав его «локатором» вместо «местоположения» или «определения местоположения», также может заставить иногда думать, что локатор службы в статье ссылается на контейнер локатора служб, а не на шаблон локатора службы (анти-) , особенно когда есть связанный шаблон, называемый Injection Dependency, а не Injector Dependency Injector.




Links