扩展方法,构建器模式和流畅的接口有什么区别?

时间:2017-07-24 10:07:25

标签: scala extension-methods fluent-interface builder-pattern

在Scala中 - 我们can do扩展方法如下:

object MyExtensions {
  implicit class RichInt(val i: Int) extends AnyVal {
    def square = i * i
  }
}

我们可以像这样使用它:

import MyExtensions._
Int i = 2;
Val squared = i.square()
Val cubed = i.square().square()

我们可以do the builder模式这样:

sealed abstract class Preparation  
case object Neat extends Preparation
case object OnTheRocks extends Preparation
case object WithWater extends Preparation

sealed abstract class Glass
case object Short extends Glass
case object Tall extends Glass
case object Tulip extends Glass

case class OrderOfScotch(val brand:String, val mode:Preparation, val isDouble:Boolean, val glass:Option[Glass])

class ScotchBuilder {
  private var theBrand:Option[String] = None
  private var theMode:Option[Preparation] = None
  private var theDoubleStatus:Option[Boolean] = None
  private var theGlass:Option[Glass] = None

  def withBrand(b:Brand) = {theBrand = Some(b); this} /* returning this to enable method chaining. */
  def withMode(p:Preparation) = {theMode = Some(p); this}
  def isDouble(b:Boolean) = {theDoubleStatus = some(b); this}
  def withGlass(g:Glass) = {theGlass = Some(g); this}

  def build() = new OrderOfScotch(theBrand.get, theMode.get, theDoubleStatus.get, theGlass);
}



object BuilderPattern {
  class ScotchBuilder(theBrand:Option[String], theMode:Option[Preparation], theDoubleStatus:Option[Boolean], theGlass:Option[Glass]) {
    def withBrand(b:String) = new ScotchBuilder(Some(b), theMode, theDoubleStatus, theGlass)
    def withMode(p:Preparation) = new ScotchBuilder(theBrand, Some(p), theDoubleStatus, theGlass)
    def isDouble(b:Boolean) = new ScotchBuilder(theBrand, theMode, Some(b), theGlass)
    def withGlass(g:Glass) = new ScotchBuilder(theBrand, theMode, theDoubleStatus, Some(g))

    def build() = new OrderOfScotch(theBrand.get, theMode.get, theDoubleStatus.get, theGlass);
  }

  def builder = new ScotchBuilder(None, None, None, None)
}

我们可以像这样使用它:

import BuilderPattern._

val order =  builder withBrand("Takes") isDouble(true) withGlass(Tall)  withMode(OnTheRocks) build()

我们可以像这样do the fluent界面:

class Person {
    protected var fname = ""
    protected var lname = ""
    def setFirstName(firstName: String): this.type = {
        fname = firstName
        this
    }
    def setLastName(lastName: String): this.type = {
        lname = lastName
        this
    }
}

class Employee extends Person {
  protected var role = ""
  def setRole(role: String): this.type = {
      this.role = role
      this
  }
  override def toString = {
      "%s, %s, %s".format(fname, lname, role)
  }
}

我们可以像这样使用它:

object Main extends App {
    val employee = new Employee
    // use the fluent methods
    employee.setFirstName("Al")
            .setLastName("Alexander")
            .setRole("Developer")
    println(employee)
}

这三个都为内部DSL提供了类似的接口。

我的问题是:扩展方法,构建器模式和流畅的界面有什么区别?

1 个答案:

答案 0 :(得分:1)

这三个完全独立的概念可以做不同的事情。

扩展方法允许您将方法添加到已存在的类中。这可以导致比创建一个将该类的对象作为参数接收的方法更好的API。

构建器模式允许您通过首先在可变对象中设置这些参数,然后调用" build"来构建具有许多选项和参数的对象。初始化您正在创建的(通常是不可变的)对象的方法。这很有用,因为它消除了对具有许多参数的巨大构造函数的需要,并且当其中一些参数对于默认值是可选的时特别有用。

流畅的API意味着" setter"方法将返回对象本身而不是返回Unit / void。这允许您可以将方法调用链接在一起的API。例如使用虚构的Point2d类

val point = new Point2d().setX(3).setY(5)

使用流畅的API

val point = new Point2d()
point.setX(3)
point.setY(5)

没有流畅的API