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

代码输出结果是:

调用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" }

方法的执行结果:

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

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

scala学习手记28 - Execute Around模式的更多相关文章

  1. scala学习手记40 - case表达式里的模式变量和常量

    再来看一下之前的一段代码: def process(input: Any) { input match { case (a: Int, b: Int) => println("Proc ...

  2. scala学习手记23 - 函数值

    scala的一个最主要的特性就是支持函数编程.函数是函数编程中的一等公民:函数可以作为参数传递给其他函数,可以作为其他函数的返回值,甚至可以在其它函数中嵌套.这些高阶函数称为函数值. 举一个简单的例子 ...

  3. scala学习手记40 - 使用case类

    前面两节我们已经多次接触过case关键字了.case关键字不仅可以用在match/case中来执行模式匹配,也可以用来修饰类.不过用case修饰的类也主要是用来做模式匹配.在上一节曾经提到过match ...

  4. scala学习手记38 - 方法命名约定和for表达式

    方法命名约定 之前在学习<运算符重载>一节时曾经说过一个方法命名约定:方法的第一个字符决定了方法的优先级.现在再说另一个命名约定:如果方法以冒号(:)结尾,则调用目标是运算符后面的实例. ...

  5. scala学习手记34 - trait方法的延迟绑定

    trait的方法的延迟绑定就是先混入的trait的方法会后调用.这一点从上一节的实例中也可以看出来. 下面再来看一个类似的例子: abstract class Writer { def write(m ...

  6. scala学习手记17 - 容器和类型推断

    关于scala的类型推断前面已经提到过多次.再来看一下下面这个例子: import java.util._ var list1: List[Int] = new ArrayList[Int] var ...

  7. scala学习手记8 - 自适应的默认做法

    scala有一些默认做法,会让代码更简洁.更易读写,下面列出了这样几个特性: 1. 支持脚本.scala支持脚本,因此无须将所有的代码都放到类里.如果脚本可以满足需求,就将代码放到一个脚本里,无须再创 ...

  8. scala学习手记3 - var和val

    scala中用var和val定义变量都是可以的. 用val定义的变量是不可变的,被初始化后值就固定下来,不可以再被修改(这类似于java中的final关键字):用var定义的变量是可变的,可以任意修改 ...

  9. Scala学习手记1 - 快速体验

    又重新开始了scala的学习,因为中断了太长时间,所以这次还得从零开始.学习的过程就记录在这个博客上了. 这次学习的教程是<scala程序设计 java虚拟机多核编程实战>,我在多看上买了 ...

随机推荐

  1. 【谷歌浏览器】在任意页面运行JS

    1.使用谷歌浏览器的调试功能: 在任何页面上运行代码片段 · Chrome 开发者工具中文文档 注:比较简单,直接,不过只能本地执行,只能自己使用.且需自行保存JS文件: 2.使用油猴插件: Tamp ...

  2. PAT 1016 Phone Bills(模拟)

    1016. Phone Bills (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue A long-di ...

  3. java编程思想 英文版 打卡

    计划 2017.3.1 购入 准备花一个月的时间阅读完, 共1500页,最后两章是GUI的内容,只需要到1300页就行了 目的有三: 熟悉java基础 提升英语阅读能力,好久没读英文书籍了 补补oop ...

  4. 目标检测系列 --- RCNN: Rich feature hierarchies for accurate object detection and semantic segmentation Tech report

    目标检测系列 --- RCNN: Rich feature hierarchies for accurate object detection and semantic segmentation Te ...

  5. Powershell Get Domain Mailbox的几种方法

    一.Disconnected Mailboxes 1.Finding Disconnected Mailboxes The first function is called Get-Disconnec ...

  6. Outlook Top of Information Store

    Actually I got to thinking this might make a good blog post so I took a closer look - Try this: On t ...

  7. caffe使用(1)

    caffe使用 caffe是一个卓越的CNN框架 caffe源码是Cpp语言的,基于一些外部的库,包括BLAS(矩阵计算),CUDA(GPU驱动),gflags,glog,boost,protobuf ...

  8. 编译安装cmake3

    编译安装cmake3 ubuntu 14 的系统默认安装的是cmake2.7,apt-get upgrade之后也还是cmake2.7,而很多软件如今需要3及以上的版本来进行cmake编译(如caff ...

  9. *.hbm.xml映射文件的元素及属性

    1. 每个持久化对象都需要提供一个以类名命名的映射文件,映射文件需要放在和po类同一目录下. 2. 如下是wefepo的映射文件: <hibernate-mapping> <clas ...

  10. HTTP协议简要介绍

    1. 网络基础 TCP/IP 通常使用的网络是在TCP/IP协议簇基础上运作的. HTTP属于它内部的一个子集. TCP/IP分为4个层次, 应用层, 传输层, 网络层, 链路层. (Applicat ...