创建Service层和DAO层(接口+实现)还是仅实现?

7
我对创建服务层和DAO层的结构感到困惑: 在一些例子中,我看到有些人为服务和DAO都创建了接口+实现,而在其他例子中,我看到有些人只创建了实现,特别是当DAO扩展了包含通用方法的AbstractDao类时,我对该选择或另一个选择的原因以及最佳实践(通常使用的)感到困惑,请给予建议。
7个回答

6

我建议为服务和DAO创建接口。很多时候,您会希望在使用此服务的代码的单元测试中模拟服务。 例如Spring强制您在使用某些Spring代理(例如事务)时使用接口。因此,您应该为服务创建一个接口。

DAO是更内部的部分,但我总是尝试为它们使用接口来简化测试。


请问您能否提供更多的细节,例如示例和参考资料,因为我需要说服一些同事。 - fresh_dev

2

我喜欢接口加具体实现的方式,原因如下:

  • 接口成为了合同:它告诉您可以调用什么,并且只要结果符合预期,您就不必担心其实现方法。
  • 您可以创建接口的可定制实现而不会破坏同一接口的其他实现(通常在编写单元测试时非常有用)。仅自定义已实现的类可能会带来更多错误,这些错误很容易被忽略。
  • 它创建了可以记录文档的框架。

实现的子类用于创建符合接口合同的业务/应用程序逻辑。


如果DAO扩展了包含CRUD操作通用方法的BasicDao,那么接口是否重要呢?因为我可以覆盖BasicDao中的通用方法。 - fresh_dev
你可以重写方法,但方法签名将保持不变。实质上,用户不会知道该方法是子类化的,只对从服务/DAO返回的数据感兴趣。 - Buhake Sindi
如果在DAO中使用了通用的AbstractDao类,最好也使用接口。 - fresh_dev
最好的情况是,一些使用DAO在Cassandra表上,这根本不需要任何数据库连接(但例如需要Thrift连接)。接口“隐藏”了所有这些无关紧要的内容。 - Buhake Sindi

1

我只实现了服务层,没有关心接口(除非必要)。 我可能应该写接口,但是到目前为止还没有遇到问题。我在没有模拟服务层的情况下很好地进行单元测试。

此外,我没有DAO层,因为我正在使用Hibernate,它似乎有些过度。 我的许多理由都基于 Bozho精心撰写的博客

我认为是否需要DAO和Hibernate是 非常有争议的,但是我对我的决定非常满意,我传递厚重的领域对象,然后只需调用Hibernate会话。 DAO层上的每个方法实际上只有一行代码(session.persist(mObject)或类似代码)。

我听到的一个反对意见是DAO层将使以后更容易更改/删除ORM。 我不确定在第一次编写DAO层所花费的时间加上更改所需的时间是否比单独编写更改的时间少。 我从未在工作中改变过ORM技术,因此风险较小。


你直接在服务层中使用 Hibernate 方法吗? - fresh_dev
1
我会做同样的事情。在出现多个实现时,从实现开始并引入接口。然而,如果服务应该在一开始就对许多客户可见 - 那么引入接口似乎是合理的。 - Piotr Nowicki

1
在我看来,当你说“服务”时,你应该有接口。如果你不能或不愿提供,那么你就没有服务和消费者之间的合同,它就不再是服务了,你可以称其为其他任何东西。

0

接口+实现的方式用于实现松耦合。这样你可以很容易地更改或切换实现,而不需要进行大量代码修改。

想象一下这样一个场景:你正在使用Hibernate进行持久化(DAO层),但是你需要切换到JPA、iBatis或任何其他ORM。如果你使用接口,你只需编写特定于JPA的实现,然后将其“插入”到Hibernate的位置即可。服务代码保持不变。


如果我使用一个包含通用CRUD操作方法的AbstractDao,并且所有DAO都扩展了该AbstractDao,那么这是否足够,而不是使用接口与DAO一起使用?还是我需要同时扩展BasicDao并实现接口? - fresh_dev

0

接口+实现模型的另一个优点是Java本身支持接口代理,而创建实现代理需要使用诸如cglib之类的库。这些代理对于事务支持等方面是必要的。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接