0

在斯卡拉 - 我們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。

我的問題是:擴展方法,構建器模式和流暢接口之間有什麼區別?

回答

0

這是三個完全分開的概念,它們完成不同的事情。

擴展方法允許您將方法添加到已存在的類中。這可以導致一個更好的API,而不是創建一個將該類的對象作爲參數的方法。

構建器模式允許您通過首先在可變對象中設置這些參數來構造一個包含許多選項和參數的對象,然後調用「構建」方法來初始化您正在創建的(通常是不可變的)對象。這很有用,因爲它不需要使用許多參數的巨大構造函數,並且在某些參數是可選的缺省值時特別有用。

流暢的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

相關問題