Scala开发教程(48): 选择瘦接口还是胖接口设计

jerry Scala 2015年11月25日 收藏

Trait的一种主要应用方式是可以根据类已有的方法自动为类添加方法。也就是说,Trait可以使得一个瘦接口变得丰满些,把它变成胖接口。
选择瘦接口还是胖接口的体现了面向对象设计中常会面临的在实现者与接口用户之间的权衡。胖接口有更多的方法,对于调用者来说更便捷。客户可以捡一个完全符合他们功能需要的方法。另一方面瘦接口有较少的方法,对于实现者来说更简单。然而调用瘦接口的客户因此要写更多的代码。由于没有更多可选的方法调用,他们或许不得不选一个不太完美匹配他们所需的方法并为了使用它写一些额外的代码。
Java的接口常常是过瘦而非过胖。例如,从Java 1.4开始引入的CharSequence接口,是对于字串类型的类来说通用的瘦接口,它持有一个字符序列。下面是把它看作Scala中Trait的定义:

trait CharSequence { 
  def charAt(index: Int): Char 
  def length: Int 
  def subSequence(start: Int, end: Int): CharSequence 
  def toString(): String 
}

尽管类String成打的方法中的大多数都可以用在任何CharSequence上,Java的CharSequence接口定义仅提供了4个方法。如果CharSequence代以包含全部String接口,那它将为CharSequence的实现者压上沉重的负担。任何实现Java里的CharSequence接口的程序员将不得不定义一大堆方法。因为Scala的Trait可以包含具体方法,这使得创建胖接口大为便捷。
在Trait中添加具体方法使得胖瘦对阵的权衡大大倾向于胖接口。不像在Java里那样,在Scala中添加具体方法是一次性的劳动。你只要在Trait中实现方法一次,而不再需要在每个混入Trait的方法中重新实现它。因此,与没有Trait的语言相比,Scala里的胖接口没什么工作要做。
要使用Trait加强接口,只要简单地定义一个具有少量抽象方法的Trait——Trait接口的瘦部分——和潜在的大量具体方法,所有的都实现在抽象方法之上。然后你就可以把丰满了的Trait混入到类中,实现接口的瘦部分,并最终获得具有全部胖接口内容的类。