Scala学习笔记——(Loan Pattern)借贷模式

Scala中的Loan Pattern

 资源回收是计算机工程实践中一项重要的实现模式。对于具有GC的程序设计语言,它仅仅实现了内存资源的自动回收,而对于诸如文件IO,数据库连接,Socket连接等资源需要程序员自行实现资源的回收。
 该问题可以形式化地描述为:给定一个资源R,并将资源传递给用户空间,并回调算法f: R => T;当过程结束时资源自动释放。

- Input: Given resource: R
- OutputT
- AlgorithmCall back to user namespace: f: R => T, and make sure resource be closed on done.

因此,该实现模式也常常被称为「借贷模式」,是保证资源自动回收的重要机制。本文通过using的抽象控制,透视Scala在这个领域的设计技术,以便巩固「按名传递」技术的应用。

简单实现

/**
  * 名字调用和值调用
  */
object manage {

  def apply[R <: {def close() : Unit}, T](resource: => R)(f: R => T) = {
    var res: Option[R] = None
    try {
      res = Some(resource)
      f(res.get)
    } catch {
      case NonFatal(ex) => println(s"Non fatal exception! $ex")
    } finally {
      if(res != None) {
        println(s"Closing resource ...")
        res.get.close()
      }
    }
  }
}

等价于

object using {

  type Closeable = { def close(): Unit }

  def apply[T <: Closeable, R](resource: => T)(f: T => R): R = {
    var source = null.asInstanceOf[T]
    try {
      source = resource
      f(source)
    } finally {
      if (source != null) source.close
    }
  }

}

 统计一个文件的行数调用如下:

object TryCatchARM extends App{

  def countLines(fileName:String): Unit = {
    println("count file lines")
    using(Source.fromFile(fileName)) { source =>
      val size = source.getLines.size
      println(s"file $fileName has $size lines")
      if(size > 20) throw new RuntimeException("Big file")
    }
  }

  args foreach(arg => countLines(arg))
}

R <: {def close() : Unit}等价于type Closeable = { def close(): Unit }定义了一个Closeable的类型别名,使得T必须是具有close方法的子类型,这是Scala支持「鸭子编程」的一种重要技术。例如,File满足T类型的特征,它具有close方法。
 这样,不管是什么对象,只要它拥有一个close():Unit的函数,都可以在这里使用,并且这个close最后将被自动调用。

惰性求值

 resource: => T是按照by-name传递,在实参传递形参过程中,并未对实参进行立即求值,而将求值推延至resource: => T的调用点。
 对于本例,using(Source.fromFile(source))语句中,Source.fromFile(source)并没有马上发生调用并传递给形参,而将求值推延至source = resource语句。

你可能感兴趣的:(Scala学习笔记)