通过名称查询来询问依赖注入

时间:2011-09-08 21:31:02

标签: spring design-patterns dependency-injection type-safety yellow-pages

我发现自己正在努力解决基于字符串的“服务定位器”概念。

对于初学者来说,IoC非常棒,接口编程是最佳选择。但是我没有看到这里使用的黄页模式的好处在哪里,除了无编译的可重构性

应用程序代码将使用(Spring)容器从中检索对象。现在这很好:既然代码只需要知道所需的接口(转换为),Spring容器接口以及所需对象的名称,就会删除很多耦合。

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

当然,定位器可以填充各种Object衍生物的大量物体。

但我有点疑惑的是,按名称检索对象的'灵活性'实际上 以类型不安全,查找不安全的方式隐藏依赖 strong>:我的编译器用于检查所请求对象成员的存在,以及它的类型,现在所有这些都被推迟到运行时阶段。

我能想到的最简单,功能最好的模式是一个巨大的应用程序范围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
}

是否有方法/模式/框架要求编译器解析请求的对象,并检查它的类型是否正常?那些的DI框架是否会这样做?

非常感谢

2 个答案:

答案 0 :(得分:2)

你所描述的是反模式,简单明了。依赖注入(如果可能,通过构造函数完成)是进行控制反转的首选方法。国际奥委会的旧文章谈到服务地点是实施模式的可行方式,但在最近的着作中,你很难找到任何提倡这一点的人。

你用这句话打了一针:

  

但我对检索的“灵活性”这一事实感到有些困惑   按名称的对象实际上隐藏了类型不安全的依赖项,   查找不安全的方式:

大多数现代DI框架可以绕过类型不安全的部分,但是它们通过隐式而不是显式来隐藏依赖。

关于这个主题的好文章:

Service Locator is an Anti-Pattern

答案 1 :(得分:2)

Spring是我使用的唯一DI框架,所以我不能代替其他人,但即使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()方法的IOC容器。 DI肯定会解决与服务定位器模式相同的问题,但它是朝着摆脱服务定位器类的依赖性迈出的额外一步。