scala学习手记28 - Execute Around模式

我们访问资源需要关注对资源的锁定、对资源的申请和释放,还有考虑可能遇到的各种异常。这些事项本身与代码的逻辑操作无关,但我们不能遗漏。也就是说进入方法时获取资源,退出方法时释放资源。这种处理就进入了Execute Around模式的范畴。

在scala里可以用函数值实现这种模式。下面是一个示例,使用Resource类演示了事务的开启和释放:

class Resource private() {
  println("Starting transaction...")

  private def cleanUp() {
    println("Ending transaction...")
  }

  def op1 = println("Operation 1")
  def op2 = println("Operation 2")
  def op3 = println("Operation 3")
}

object Resource {
  def use(codeBlock: Resource => Unit) {
    val resource = new Resource try {
      codeBlock(resource)
    } finally {
      resource.cleanUp()
    }
  }
}

这段代码里将Resource类的构造器标记为private,这样就只能在Resource类内部和它的伴生类中创建实例了。因为只能在这两个地方创建实例,从而保证是可以按照确定的方式使用这个类的对象了,也就可以保证其行为是按照确定的方式执行。cleanUp()方法也被标记为private,确保不会被意外调用。第一行的print语句是具体事务操作的占位符。调用构造函数时,事务启动;调用cleanUp()函数时,事务终结。此外Resource类中还准备了一些实例方法,如op1()、op2()等。

在伴生对象里有一个默认public的方法use,它接收一个函数值作为参数。use()方法创建了一个Resource的实例,在try和finally块的保护之下,把这个实例传给了给定的函数值。在finally块里,调用了Resource私有实例方法cleanUp()。

看一下是如何使用Resource类的:

Resource.use { resource =>
  resource.op1
  resource.op2
  resource.op3
  resource.op1
}

代码输出结果是:

image

调用Resource的伴生对象时,会自动创建一个Resource实例,等到传递的函数值执行结束后,会自动调用cleanUp方法释放占用的资源。

上面模式的一个变体是Loan模式。如果想确保非内存资源得到确定性释放,就可以使用这个模式。可以这样认为这种资源密集型的对象是借给你的,用过之后应该立即归还。

下面是一个Loan模式的例子:

import java.io._

def writeToFile(fileName: String)(codeBlock: PrintWriter => Unit) = {
  val writer = new PrintWriter(new File(fileName))
  try {
    codeBlock(writer)
  } finally {
    writer.close()
  }
}

现在调用writeToFile()将一些内容写入文件:

writeToFile("output.txt") { writer => writer write "hello from Scala" }

方法的执行结果:

image

作为writeToFile()方法的使用者,我们不必操心文件的关闭。在代码块里,这个文件是借给我们用的。我们可以用得到的PrintWriter实例进行写操作,一旦从这个块返回,方法就会自动关闭文件。

###############

posted @ 2016-07-30 10:40  robin·张  阅读(743)  评论(0编辑  收藏  举报