OOP:在哪些情况下,基于类的设计比基于接口的设计更好?


10

我正在阅读 JDOM的网站

为什么用具体的类而不是接口来定义JDOM API?

Jason Hunter总结了针对JDOM的基于接口的API的论点:

使用接口,所有东西都变成了工厂,必须将元素“导入”到新文档中,而不是仅仅添加元素,不能保证诸如长期序列化之类的功能,因此清单还在继续。

我们实际上是从接口开始的。在对某些同伴的发行前审查中,我们收到了反馈,应该尝试具体的课程。我们做到了,并且设计对此要好得多。

我是初学者。到目前为止,我所听到的所有建议都建议不要将设计与具体类一起使用。

可能在某些地方使用具体的类是适当的。是否存在在设计中使用具体类的常见类问题?



:您还可以检查出“限制你的抽象”系列ayende.com/blog/153889/...
henginy

“我们做到了,并且设计对此要好得多。” -怎么样了?
CodeART 2012年

Answers:


6
  • 继承创建了对实现的依赖,这可能是关于可维护性的大问题。必然的结果是,在处理数据传输对象时可以安全地使用继承和具体类,根据定义,这些对象几乎不包含任何实现。需要此依赖性时,也可以使用具体类的继承。在这种情况下,您可能需要使用一个抽象类,该抽象类在层次结构的顶部包含通用方法(通常是实用程序函数)。
  • 在使用具体的类层次结构时,请不要忘记应用Liskov替换原理
  • 为客户端使用具体类(即使用的类,而不是使用的类)没有问题。
  • 恕我直言,您可以使用具体的类,直到有事情要更改。在打开/关闭原则 会告诉你使用的接口以避免耦合,但对于你是不是也会需要的原则,你可能会考虑使用具体的类,直到那一刻,当你需要改变一些东西在执行。问题是,第一次在某处发生任何更改时,您将必须更改类的每个客户端。虽然只有一种可能的工具可以执行某些操作,但是可以使用IMO的具体类。

[编辑] JDOM的网站以java.io.File为例,但这绝对是一种基于接口的设计,因为它可以像只是可序列化的那样操作java.io.File实例。在这种情况下,只有“创造者”才能知道具体的阶层


浮动的“值对象”有两个相互矛盾的定义。您的似乎不太常见,也称为“数据传输对象”。
Michael Borgwardt'5

@MichaelBorgwardt Thx指出了这一点,因为我并非仅表示“数据传输对象”:我编辑我的答案
Matthias Jouan,2012年

1
LSP对于任何子类型关系,接口实现以及继承都很重要。

3

从JDOM站点:

Jason(Hunter)与Brett McLaughlin于2000年初共同创立了JDOM项目

也就是说,大约在引入Java 1.3的时候。关于Java开发,没有什么成熟的方法-最有经验的开发人员最多只能使用Java四年。没有广泛使用的IoC容器,没有Hibernate。Apache Struts才刚刚起步。

这就是说杰森和布雷特错了。许多人还没有“得到它”。如果他们有C ++背景,那么,您就不需要C ++中的接口(好吧,它们在C ++中,但是您实际上并不需要它们,对吗?),为什么在Java中使用它们呢?好吧,这里有很多充分的理由,其他人可以将您引导到。

他们肯定是错的

接口可以完成的任何事情都可以通过子类完成

Java不允许类的多重继承,但是它允许多个接口的实现。那可以带来真正的改变。


3

请记住,关于您的问题,在软件开发中有多种方法可以解决问题,并且如果某些开发人员使用与您不同的技术,这并不意味着解决方案是错误的。

其中一种情况是“接口”与(基础)“类”。在某些情况下,两种技术都可以达到相同的目标。

让事情变得更复杂的是,有几种接口的使用,仅需提及:

  • 一种是设计“合同”或“规范”而无需“实施”
  • 其他,以向现有的(不是新的)类或类层次结构添加功能
  • 作为对先前内容的补充,允许在不同对象,技术之间进行共享访问,例如:Enterprise Beans,CORBA,COM,WebServices
  • 模拟多重继承

您的问题适用于第一点。

当您要开发一个类层次结构,而不仅仅是一个类,并且几个类打算共享某些特定功能时,即使可以通过接口完成,您也可能要从基类开始。

并且,将接口留给其他方案。

小部件(控件)库就是一个很好的例子。

我建议,看看其他编程语言如何使用接口和类,例如:PHP,Delphi(对象Pascal),C#。

干杯。


1

API设计规则实际上是一件事。我不确定您应该如何设计日常代码来总结该FAQ中的任何内容。

对于常规代码,您仍然会使用接口或抽象类继承而不是原始继承IMO。

为了更好地理解该规则,您不仅要从派生类与其父类的角度出发,而且要从一个对另一个对象具有依赖性的对象的角度出发。最好总是依赖于抽象而不是具体的实现,因为它允许您接受整个系列的不同类作为依赖项,而不是依赖它们的协定而不是它们的实现细节。

第一次使用通常是在单元测试中-如果您真的想完全隔离地对类进行单元测试,则可以针对与生产环境中使用的实际实现不同的依赖关系的虚假实现进行此操作。


0

通常,您需要一个接口作为任何通过参数传递或返回的接口,从本质上讲,您可以将类与其依赖项分离。

因此,如果我们正在寻找一门课程,我们通常不会想到通常会发生异常。我不是Java开发人员,但是可以肯定,在其他类似语言中,我认为我没有看到为异常定义的接口。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.