11

我认为标题不言自明——如果该接口只有 1 个具体实现,我为什么要编写一个接口然后实现一个具体类?

4

11 回答 11

36

我认为你不应该;)

无需使用相应的接口来隐藏所有类。

即使您稍后要进行更多实现,也可以在必要时随时提取接口。

于 2009-10-05T13:07:28.607 回答
13

这是一个粒度问题。您不能用不必要的接口使代码混乱,但它们在层之间的边界处很有用。

有一天你可能会尝试测试一个依赖于这个接口的类。然后很高兴你可以嘲笑它。

我不断地创建和删除接口。有些不值得努力,有些确实需要。我的直觉大部分是正确的,但一些重构是必要的。

于 2009-10-05T13:07:45.227 回答
5

问题是,如果只有一个具体的实现,是否应该有一个接口?

于 2009-10-05T13:06:15.697 回答
2

YAGNI - 你不需要它来自维基百科

根据那些提倡 YAGNI 方法的人的说法,编写目前不需要但将来可能需要的代码的诱惑具有以下缺点:

* The time spent is taken from adding, testing or improving necessary functionality.
* The new features must be debugged, documented, and supported.
* Any new feature imposes constraints on what can be done in the future, so an unnecessary feature now may prevent implementing a necessary feature later.
* Until the feature is actually needed, it is difficult to fully define what it should do and to test it. If the new feature is not properly defined and tested, it may not work right, even if it eventually is needed.
* It leads to code bloat; the software becomes larger and more complicated.
* Unless there are specifications and some kind of revision control, the feature may not be known to programmers who could make use of it.
* Adding the new feature may suggest other new features. If these new features are implemented as well, this may result in a snowball effect towards creeping featurism.
于 2009-10-05T13:47:55.183 回答
1

您的问题的两个有些矛盾的答案:

  1. 您不需要从您构建的每个具体类中提取接口,并且
  2. 大多数 Java 程序员没有构建应有的接口。

大多数系统(甚至是“一次性代码”)的发展和变化远远超出了它们最初的设计意图。接口通过减少耦合帮助它们灵活地增长。一般来说,以下是您应该对接口进行编码的警告信号:

  1. 您是否甚至怀疑另一个具体类可能需要相同的接口(例如,如果您怀疑您的数据访问对象可能需要 XML 表示形式——这是我所经历的)?
  2. 您是否怀疑您的代码可能需要位于 Web 服务层的另一端?
  3. 您的代码是否为某些外部客户端形成了服务层?

如果您可以诚实地对所有这些问题回答“不”,那么界面可能会过大。可能。但同样,不可预见的后果是编程游戏的名称。

于 2009-10-05T13:18:03.227 回答
1

您需要通过指定公共函数来决定编程接口是什么。如果你没有做好这一点,这个类将很难使用。

因此,如果您稍后决定需要创建一个正式的界面,您应该准备好开始设计。

所以,你确实需要设计一个接口,但你不需要把它写成一个接口然后实现它。

于 2009-10-05T13:34:56.910 回答
1

我使用测试驱动的方法来创建我的代码。这通常会导致我创建接口,我想在其中提供一个模拟或虚拟实现作为我的测试夹具的一部分。

我通常不会创建任何代码,除非它与我的测试有一些相关性,并且由于您无法轻松测试接口,只有实现,如果我在为测试用例提供依赖项时需要它们,我会创建接口。

我有时也会在重构时创建接口,以消除重复或提高代码的可读性。

如果你以后发现需要一个接口,你总是可以重构你的代码来引入一个接口。

唯一的例外是如果我正在设计一个 API 以发布给第三方——在这种情况下,更改 API 的成本很高。在这种情况下,我可能会尝试预测我将来可能需要进行的更改类型,并找出创建 API 的方法,以尽量减少未来不兼容的更改。

于 2009-10-05T14:13:47.320 回答
1

One thing which no one mentioned yet, is that sometimes it is necessary in order to avoid depenency issues. you can have the interface in a common project with few dependencies and the implementation in a separate project with lots of dependencies.

于 2009-10-05T15:01:43.300 回答
0

“永远只有一个实现” == 著名的遗言

制作一个接口然后从中派生一个具体类并不需要太多成本。这样做的过程可以让你重新思考你的设计,并且通常会带来更好的最终产品。一旦你完成了,如果你发现自己吃了这些词——经常发生——你就不必担心了。你已经准备好了。否则,您需要进行大量重构,这会很痛苦。

编辑澄清:我正在假设这个类将相对广泛地传播。如果它是单个包中的一个或两个其他类使用的一个小型实用程序类,那么是的,不用担心。如果它是一个将由多个其他类在多个包中使用的类,那么我之前的回答适用。

于 2009-10-05T13:11:26.897 回答
0

问题应该是:“你怎么能确定只有一个具体的实现?”

你怎么能完全确定?

当您考虑到这一点时,您应该已经创建了界面,并且可以在没有可能被证明是错误的假设的情况下继续前进。

使用当今的编码工具(如 Resharper),在类旁边创建和维护接口确实不需要太多时间,而发现现在需要额外的实现并替换所有具体引用可能需要很长时间,而且一点都不好玩——相信我。

于 2009-10-05T13:19:26.487 回答
0

其中很多内容来自于 Rainsberger 在 InfoQ 上的演讲:http: //www.infoq.com/presentations/integration-tests-scam

上课有3个理由:

  1. 它有一些价值
  2. 它有助于坚持一些实体
  3. 它执行一些服务

大多数服务应该有接口。它创建了一个边界,隐藏了实现,并且您已经有了第二个客户端;与该服务交互的所有测试。

基本上,如果你想在单元测试中模拟它,它应该有一个接口。

于 2009-10-05T13:42:41.767 回答