2014-03-13 158 views
2

我发现,亦常在我的代码我这样做(使用吉斯我的DI框架):依赖注入和观察者模式

public class SomeObserver implements IObserver { 
    @Inject 
    SomeObserver(IObservable observable) { 
     observable.subscribe(this); 
    } 
    // Snip 
} 

它发生在我最近,当测试,我现在需要的至少将一个模拟传递给我的程序,这并不一定是最糟糕的事情,但它至少依赖于该接口的依赖关系。另一种选择是,在生产中,做到这一点:

public class SomeModule extends AbstractModule { 
    // snip 

    @Provides 
    protected SomeObserver provideSomeObserver(IObservable observable) { 
     SomeObserver newObject = new SomeObserver(); 
     newObject.subscribe(observable); 
    } 
} 

然后在测试中,我没有甚至到Observable参考。但是,如果我想更改构造函数,模块也必须更改(在第一个示例中它不会)。

哪个更好?还是有更好的第三选择?


更新:我想谈一谈我的用例。

考虑一个数据处理应用程序,其中数据源是Observable。我不想让数据源了解系统的其他部分(Separation of Concerns)。数据被过滤到至少三个不同的观察者中,他们从事独立的任务。我想保持数据源可交换 - 用于测试,分离问题等原因,所以数据源只是实现我定义的接口,然后您可以拨打.subscribe(this)

然后,我使用依赖注入和模块来确定接线如何。如果我选择这个解决方案,我还可以使用注释来澄清注入。

因此,本质上,我使用依赖注入来管理布线,这正是我最初认为的原因;创造,例如,ObservationManager似乎很多boilerplate收益不大。但是,我可能会错过一些东西。

+0

活动巴士怎么样? – condit

+0

@condit同样的问题,那么我需要模拟事件总线或者至少创建一个对它的引用。如果我在测试用例中手动传递消息,那么这不相关。 – durron597

+0

您仍然可以在测试中使用事件总线的实例。使用Guava的'EventBus',这就像每个测试(或测试套件,如果你愿意)实例化一个新事物一样简单,并且使用'EventBus'。而不是将它传递给构造函数(或第二个例子中的提供者)。 – moofins

回答

1

它看起来像你滥用依赖注入。

顾名思义,依赖注入旨在解决解决类依赖问题。但语义观察者和可观察者并不相互依赖。他们真的不应该被视为依赖。

建立观察者可观察关系本身是一项单独的任务,所以理想情况下应该有第三个实体依赖于观察者和可观察并建立它们之间的关系。在这种情况下使用事件总线看起来相当正交,因为它仍归结为订阅,订阅应该在某处完成。

事实上,你已经注意到在这种情况下使用mock是一个奇怪的事情,这是一个你试图用作依赖的东西,它根本不是一个依赖。对于正常的依赖关系(直接由类使用),提供模拟对象是完全可以的,它们完全是为了这个目的而设计的。

+0

谢谢你的回答。我更详细地介绍了我的用例,以使问题更加清晰。顺便说一句,我同意使用事件总线是正交的问题。 – durron597

+0

@ durron597,不,创建你所谓的'ObservableManager'不是样板。锅板意味着你必须编写大量的代码才能获得很少的结果。但在这种情况下,您只需将构造函数的逻辑移至单独的类。除了类定义之外,没有额外的代码,所以我不会称之为样板。这实际上是一个关注点的分离。而且,在配置观察者订阅的中心位置,显然,你有一个地方寻找他们。在您当前的设计中,这些订阅分布在整个代码库中。 –