我发现自己正在努力解决基于字符串的“服务定位器”概念。
对于初学者来说,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框架是否会这样做?
非常感谢
答案 0 :(得分:2)
你所描述的是反模式,简单明了。依赖注入(如果可能,通过构造函数完成)是进行控制反转的首选方法。国际奥委会的旧文章谈到服务地点是实施模式的可行方式,但在最近的着作中,你很难找到任何提倡这一点的人。
你用这句话打了一针:
但我对检索的“灵活性”这一事实感到有些困惑 按名称的对象实际上隐藏了类型不安全的依赖项, 查找不安全的方式:
大多数现代DI框架可以绕过类型不安全的部分,但是它们通过隐式而不是显式来隐藏依赖。
关于这个主题的好文章:
答案 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肯定会解决与服务定位器模式相同的问题,但它是朝着摆脱服务定位器类的依赖性迈出的额外一步。