我在代码中经常发现这样做(使用Guice作为我的DI框架):
public class SomeObserver implements IObserver {
@Inject
SomeObserver(IObservable observable) {
observable.subscribe(this);
}
// Snip
}
最近我想到,在测试时,我现在需要至少将一个模拟传递给我的程序,这不一定是最糟糕的事情,但它确实依赖于至少将依赖项绑定到{{1接口。另一种选择是,在生产中,这样做:
IObservable
然后在测试中,我甚至不必引用public class SomeModule extends AbstractModule {
// snip
@Provides
protected SomeObserver provideSomeObserver(IObservable observable) {
SomeObserver newObject = new SomeObserver();
newObject.subscribe(observable);
}
}
。但是,如果我想要更改构造函数,模块也必须更改(在第一个示例中它不会更改)。
哪个更好?或者是否有更好的第三种选择?
更新:我想稍微谈谈我的用例。
考虑一个数据处理应用程序,其中数据源是Observable。我不希望数据源知道系统的其他部分(Separation of Concerns)。数据被过滤到至少三个不同的观察者,他们从事独立任务。我想保持数据源可交换 - 用于测试,关注点分离等原因,因此数据源只是实现了我定义为Observable
接口的内容,然后你可以调用{{1 }}
然后,我使用依赖注入和模块来确定接线的确切方式。如果我选择,这个解决方案还允许我decorate可观察,使用注释来澄清注射。
所以,基本上,我正在使用依赖注入来管理布线,这正是我原来的想法;比如创建Subscribable<Observer>
似乎很多boilerplate获得的收益很少。但同样,我可能会遗漏一些东西。
答案 0 :(得分:2)
看起来你有点滥用依赖注入。
依赖注入,顾名思义,旨在解决解决类依赖关系的问题。但语义观察者和观察者并不依赖于彼此。他们真的不应该被视为依赖。
设置观察者可观察关系本身就是一个单独的任务,所以理想情况下你应该有一个依赖于观察者和可观察者的第三个实体,并建立它们之间的关系。在这种情况下,使用事件总线看起来非常正交,因为它仍然归结为订阅,订阅应该在某处完成。
事实上,你已经注意到在这种情况下使用模拟是一种奇怪的信号是你试图用作依赖的东西而不是依赖。对于普通的依赖项(直接由类使用),提供模拟对象是完全可以的,毕竟它们是完全符合的。