论坛首页 Java企业应用论坛

请教:关于接口的设计

浏览 70862 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-03-03  
:)

有道理。我会记住的。谢谢。

今天看到一篇好东西,与这个主题相关,分享给大家:
(来自熊节的网站)
==================================================
接口和抽象类
在去年的12 月初, 我在Design Patterns Explained 的讨论组上看到这个系列帖子,
觉得很有意思, 所以整理出来。如果你喜欢这种形式, 请写信到gigix@263.net, 我会整理
更多有趣的帖子出来。
面向对象中有一个术语: 派生。在用Java 编程的时候, 派生的来源可以是抽象类
( abstract class)、也可以是接口( interface)。何时使用抽象类? 何时使用接口? 这几
个帖子正是讨论了这个问题。
( 提出问题)
Alan, 我买了你的书, 读到了其中“ Bridge 模式” 那一章。然后, 我把一位朋友— —
他是个Java专家, 有五、六年使用Java的经验— — 叫来, 把你的书给他看, 并请他为我解
释你的Java 代码。我自己比较偏向于使用接口, 而你更多的使用了抽象类。他得出的结论
是: 你偏向于使用抽象类, 这反映出你对C++的爱好多于对Java的爱好。毕竟Java才有接
口这个概念, 而C++只有抽象类。因此, 我们感觉: 如果把你的示例代码中的抽象类换成接
口, 也许会使它们更能反映出实际情况和“ 按照协议设计” 的思想。实际上, 如果读过Peter
Coad的书, 你会发现他也主要使用接口。
( Alan Shalloway 的答复)
感谢你对这本书的评论。
我用Java 也有五、六年了, 所以我不认为使用抽象类就表示没有经验。实际上, 我觉
得Java 的一大缺憾就是它不支持多继承, 所以开发者经常被迫使用接口, 因为继承只能使
用一次。当然了, 这里面涉及到多继承的性能问题和基类成员的名字重复问题。但是不管怎
么说, 不允许多继承总是值得质疑的。
至于我这本书, 我选择使用抽象类, 是因为大多数人都熟悉它— — 不是每个人都喜欢去
看章节后面的C++示例的, 所以我决定用这种更通用的示例。
接口的问题就是它无法拥有默认行为。如果你用接口来定义一个什么东西并希望跨过这
层封装来添加一些行为, 你就必须使用委托。在我的记忆中, 有很多次就是因为不支持默认
行为而造成了麻烦。为了绕过这个限制, 我会使用委托, 但是这也是个痛苦的事情。
BTW: 我很喜欢Coad的书— — 我认为那是有史以来最好的设计书籍之一。
( Scott Bain 的跟贴)
从我自己的角度来说, 我是一个Java程序员( 从来没用过C++)。但是每当我遇到单继
承关系的时候, 我倾向于使用抽象类, 尽管我知道Java 不支持多继承。为什么这样? 因为
即使我现在没有任何默认行为, 将来我还可以放进一些默认行为, 而不必修改子类的结构。
而且, 如果要在一个继承体系中放置工厂方法来生成子类的实例, 抽象类是就是最好、
最合乎逻辑的地方。因为客户对象只需要“ 知道” 抽象类就可以了, 通过转型得到的实例完
全封装了子类的存在和选择子类的规则。这使得系统的扩展变得简单,而且不会造成副作用。
只有当需要让一个类“ 象什么” 而非“ 是什么” 的时候, 我才会使用接口。
( Alan Shalloway 的回复)
PDF created with FinePrint pdfFactory trial version http://www.fineprint.com
精彩! 很高兴看到这样的回复! J
我也发现, 在Java 中缺少默认行为造成的影响似乎还没有真正引起人们的重视。从一
开始, SUN 似乎就忽略了向后兼容的问题。我可以大胆的预言: 完全用接口构建成的系统将
在几年之后发现这是一个大问题。据我所知, 有几个基于COM 模型( 也就是接口) 构建的应
用程序的开发者现在已经陷入了维护问题, 因为当他们想修改接口来应对新的情况( 比如添
加新的参数或新的方法) 时, 这会耗去他们大量的时间。如果使用抽象类, 修改就不会这么
困难, 因为你可以只修改默认方法, 子类就不用动了。
我可不是说不能使用接口, 但是你必须清楚: 有些时候应该使用接口, 而有些时候就是
应该使用抽象类。不幸的是, 由于Java不支持多继承, 你必须很小心的做出选择。
( Scott Bain 的跟贴)
同样精彩! 关于接口, 我再来废话几句:
有时候, 一个东西可以“ 是” 几个东西。不明白这句话吗? 我就拿我自己来举个例子吧:
我“ 是”一个程序员、一个老师、一个作者、一个父亲… … 你可以说我“ 实现了老师的接口”,
学生们会向我询问关于上课的问题。我还“ 实现了父亲的接口”, 但是我的学生可能知道这
一点, 也可能不知道。如果他们知道这一点, 他们就可以放心的向我询问关于抚养小孩的问
题了。
但是, 尽管我实现了所有这些接口, 我还有一个抽象类— — “ 人”。这个抽象类给我提
供了所有的默认行为( 比如说我偶尔会走背运)。
PDF created with FinePrint pdfFactory trial version http://www.fineprint.com
0 请登录后投票
   发表时间:2004-03-03  
接口的使用在于你的应用能否形成一个稳定有效的framework。
0 请登录后投票
   发表时间:2004-03-03  
确实是的,我也很想面向接口写代码,好处书上都写了。
但问题的确在于框架再初期很不稳固,主要是设计不出来稳,所以用不起来,等开发过程中框架逐渐稳固了并浮现出来了,再重构。

对这个问题解决似乎比较清晰了,再谢谢一次:)
0 请登录后投票
   发表时间:2004-03-03  
我是这样理解的,不知道对不对:
框架的接口我们就不必说了。
关于业务逻辑,分析后总能抽象出若干种对象,那么根据业务的关系每类对象都应该完成某几种功能----这就是定义接口的依据(我理解),如果业务逻辑不发生大的变化且我们对业务进行了合理的抽象,那么我们定义的接口在开发当中是不应该发生较大变化的。因此在系统分析的初期最好就按接口来进行高层次上的功能划分,等到每个接口如何实现都是以后的事情,现不用考虑。
0 请登录后投票
   发表时间:2004-03-03  
如果想作出一个快速的原型,那么就为每个接口做一个简单的实现。如果做着做着发现这几个接口的关系很别扭,那很有可能就是业务模型抽象的并不很合理。所以在做原型的时候大幅度改动代码通常是错误地划分了业务对象。
0 请登录后投票
   发表时间:2004-03-03  
流水 写道
如果想作出一个快速的原型,那么就为每个接口做一个简单的实现。如果做着做着发现这几个接口的关系很别扭,那很有可能就是业务模型抽象的并不很合理。所以在做原型的时候大幅度改动代码通常是错误地划分了业务对象。

通常的错误是需求损耗了。
0 请登录后投票
   发表时间:2004-03-03  
动物的行为,例如:走、跑、趴等,可以定义为接口,而狗或猫具有这些行为,可以为抽象类,而具体的 class,就是具体类型的狗或猫了。
0 请登录后投票
   发表时间:2004-03-03  
对于一个产品或者通用组件,使用接口就尤为重要了。
0 请登录后投票
   发表时间:2004-03-04  
抽象类和接口我还是不经常用到,因此有时候就搞不清楚什么时候该定义为抽象类,什么时候该定义为接口。我想接口好像不仅仅只为了解决多个父类的情况吧?
书上看到的东西都觉得有道理,可是一做起来就会发现很繁琐,好好的一个对象,结果七大姑、八大姨的亲戚搞了一堆,而且没一个干实事的,呵呵。
0 请登录后投票
   发表时间:2004-03-04  
流水 写道
抽象类和接口我还是不经常用到,因此有时候就搞不清楚什么时候该定义为抽象类,什么时候该定义为接口。我想接口好像不仅仅只为了解决多个父类的情况吧?


什么时候使用抽象类,什么时候用接口,我上面转贴的帖子(熊节搜集整理的)刚好谈到了这个问题,你可以再仔细看看,就是很长的那篇帖子。

流水 写道

书上看到的东西都觉得有道理,可是一做起来就会发现很繁琐,好好的一个对象,结果七大姑、八大姨的亲戚搞了一堆,而且没一个干实事的,呵呵。


正是这个原因,我才发贴问这个问题,因为我们都希望模式帮我们干些实际的事情,而不是光拿来聊天,显示高深的。

还有你所说的那种接口先清晰的定义好--这是所有人的梦想,正是由于这只是个梦想,所以才萌生了一些类似于重构之类的想法,都是为了解决这些问题。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics