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

    什么是Forge Minecraft Forge is a Minecraft application programming interface (API) which allows almost ...

  2. devmapper: Thin Pool has 162394 free data blocks which is less than minimum required 163840 free data blocks

    问题: 制作镜像的时候报错 devmapper: Thin Pool has 162394 free data blocks which is less than minimum required 1 ...

  3. 你不知道的Javascript(上卷)读书笔记之四 ---- 提升、this

    1. 提升 使用var声明的变量声明和函数的声明(函数表达式不会)会被提升至所在函数作用域顶部 a. 从编译器角度出发 回忆一下, 中关于编译器的内容,引擎会在解释 JavaScript 代码之前首先 ...

  4. 原!总结 quartz集群 定时任务 测试运行ok

    由于项目优化重构,想将定时任务从quartz单机模式变成集群或分布式的方式.于是,百度了一圈....修修改改...用集群的方式部署定时任务,测试可以... 集群?分布式?什么区别? 集群:同一个业务, ...

  5. 转!!SpringMVC与Struts2区别与比较总结

    1.Struts2是类级别的拦截, 一个类对应一个request上下文,SpringMVC是方法级别的拦截,一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上Spr ...

  6. HTTP Keep-Alive是什么?如何工作?(转)

    add by zhj: 本篇只是Keep-Alive的第一篇,其它文章参见下面的列表. 原文: HTTP Keep-Alive是什么?如何工作? 1. HTTP Keep-Alive是什么?如何工作? ...

  7. Java Synchronized 与 ThreadLocal 异同

    同:都是为了线程安全 异:synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问.而ThreadLocal为每一个线程都提供了变量的副本, 使得每个线程在某一时间访问到的并 ...

  8. JSP--JSP语法--指令---九大隐式对象--四大域对象--JSP内置标签--JavaBean的动作元素--MVC三层架构

    一.JSP 原理:JSP其实就是一个servlet. Servlet负责业务逻辑处理,JSP只负责显示.开发中,JSP中不能有一行JAVA代码 二.JSP语法 1. JSP模板元素:JSP中HTML标 ...

  9. ngs中reads mapping-pku的生信课程

    4.NGS中的reads mapping 顾名思义,就是将测序的得到的DNA定位在基因组上. 因为二代测序的得到的序列是较短的,reads mapping很好地解决了这个问题. 本质上reads ma ...

  10. 华为大数据项目fusionInsight

    项目简述:基于开源Hadoop2.0架构的集群网络,进行海量数据的分布式计算.由于Hadoop集群规模不断扩大,而搭建一个同等规模的测试集群需要一笔昂贵的开销.目前有100台左右物料,期望预测计算节点 ...