Внедрение зависимостей через поиск по имени
Я испытываю трудности с концепцией строковых "сервисных локаторов".
Начнем с того, что 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 определенно решает ту же проблему, что и шаблон локатора службы, но это еще один шаг к избавлению от зависимости от класса локатора службы.