Внедрение зависимостей через поиск по имени

Я испытываю трудности с концепцией строковых "сервисных локаторов".

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

Код приложения будет использовать контейнер (Spring) для извлечения объектов из. Теперь это хорошо: поскольку код должен знать только необходимый интерфейс (для приведения к нему), интерфейс контейнера Spring и имя нужного объекта, много связей удаляется.

public void foo(){
   ((MyInterface) locator.get("the/object/I/need")).callMe();
}

Где, конечно, локатор может быть заполнен газиллионом объектов всех видов Object производные.

Но я немного озадачен тем фактом, что "гибкость" извлечения объекта по имени фактически скрывает зависимость небезопасным, небезопасным для поиска способом: где мой компилятор проверял наличие запрошенного члена объекта, и это типа, теперь все это откладывается на этапе выполнения.

Самый простой, функционально приемлемый шаблон, который я мог придумать, - это гигантское приложение struct как объект:

public class YellowPages  {
    public MyInterface the_object_i_need;
    public YourInterface the_object_you_need;
    ....
}

// context population (no xml... is that bad?)
YellowPages locator = new YellowPages();
locator.the_object_i_need=new MyImpl("xyx",true),
locator.the_object_you_need=new YourImpl(1,2,3)


public void foo(){
   locator.the_object_i_need.callMe(); // type-safe, lookup-safe
}

Будет ли способ / шаблон /framework попросить компилятор разрешить запрошенный объект и проверить, в порядке ли его тип? Существуют ли структуры DI, которые тоже это делают?

Большое спасибо

2 ответа

Решение

То, что вы описываете, является анти-паттерном, простым и понятным. Внедрение зависимостей (по возможности, через конструктор) является предпочтительным способом инверсии управления. В старых статьях о МОК говорится о расположении службы как о жизнеспособном способе реализации шаблона, но вам будет сложно найти кого-то, кто будет пропагандировать это в более поздних статьях.

Вы ударили гвоздь по голове этим утверждением:

Но я немного озадачен тем фактом, что "гибкость" извлечения объекта по имени фактически скрывает зависимость небезопасным, небезопасным для поиска способом:

Большинство современных DI-фреймворков могут обойти небезопасную часть, но они скрывают зависимость, делая ее неявной, а не явной.

Хорошая статья на эту тему:

Сервисный локатор - это анти-паттерн

Spring - это единственная интегрированная среда DI, которую я использовал, поэтому я не могу говорить за других, но хотя Spring дает вам возможность запрашивать объект по его имени в вашем коде, вам не нужно получать ваши bean-компоненты Spring по имени - на самом деле, если вы это сделаете, вы на самом деле не извлекаете выгоду из "Я" (инверсия) в МОК.

Весь принцип Spring / DI заключается в том, что ваши объекты не должны запрашивать конкретный объект - они должны просто иметь все необходимые объекты, передаваемые ему контейнером IOC. Различие тонкое, но оно есть. Первый подход будет напоминать код, который вы вставили:

public void foo(){
   ((MyInterface) locator.get("the/object/I/need")).callMe();
}

Последний подход, напротив, не зависит от какого-либо локатора службы и не зависит от "имени" объекта, который он хочет:

private ObjectINeed objectINeed;

public void setObjectINeed(ObjectINeed objectINeed) {
    this.objectINeed = objectINeed;
}

public void foo(){
   objectINeed.callMe();
}

Это контейнер МОК, который вызывает setObjectINeed() метод. DI определенно решает ту же проблему, что и шаблон локатора службы, но это еще один шаг к избавлению от зависимости от класса локатора службы.

Другие вопросы по тегам