Внедрение зависимостей через поиск по имени - PullRequest
1 голос
/ 09 сентября 2011

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

Начнем с того, что 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 ]

2 голосов
/ 09 сентября 2011

Spring - единственная интегрированная среда DI, которую я использовал, поэтому я не могу говорить за других, но хотя Spring дает вам возможность запрашивать объект по его имени в вашем коде, вы не имейте , чтобы получить свои Spring bean-компоненты по имени - фактически, если вы это сделаете, вы на самом деле не используете «I» (инверсию) в IOC.

Весь принцип, заложенный в 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();
}

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

2 голосов
/ 09 сентября 2011

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

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

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

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

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

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

...