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
}
代码输出结果是:

调用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模式的更多相关文章
- scala学习手记40 - case表达式里的模式变量和常量
再来看一下之前的一段代码: def process(input: Any) { input match { case (a: Int, b: Int) => println("Proc ...
- scala学习手记23 - 函数值
scala的一个最主要的特性就是支持函数编程.函数是函数编程中的一等公民:函数可以作为参数传递给其他函数,可以作为其他函数的返回值,甚至可以在其它函数中嵌套.这些高阶函数称为函数值. 举一个简单的例子 ...
- scala学习手记40 - 使用case类
前面两节我们已经多次接触过case关键字了.case关键字不仅可以用在match/case中来执行模式匹配,也可以用来修饰类.不过用case修饰的类也主要是用来做模式匹配.在上一节曾经提到过match ...
- scala学习手记38 - 方法命名约定和for表达式
方法命名约定 之前在学习<运算符重载>一节时曾经说过一个方法命名约定:方法的第一个字符决定了方法的优先级.现在再说另一个命名约定:如果方法以冒号(:)结尾,则调用目标是运算符后面的实例. ...
- scala学习手记34 - trait方法的延迟绑定
trait的方法的延迟绑定就是先混入的trait的方法会后调用.这一点从上一节的实例中也可以看出来. 下面再来看一个类似的例子: abstract class Writer { def write(m ...
- scala学习手记17 - 容器和类型推断
关于scala的类型推断前面已经提到过多次.再来看一下下面这个例子: import java.util._ var list1: List[Int] = new ArrayList[Int] var ...
- scala学习手记8 - 自适应的默认做法
scala有一些默认做法,会让代码更简洁.更易读写,下面列出了这样几个特性: 1. 支持脚本.scala支持脚本,因此无须将所有的代码都放到类里.如果脚本可以满足需求,就将代码放到一个脚本里,无须再创 ...
- scala学习手记3 - var和val
scala中用var和val定义变量都是可以的. 用val定义的变量是不可变的,被初始化后值就固定下来,不可以再被修改(这类似于java中的final关键字):用var定义的变量是可变的,可以任意修改 ...
- Scala学习手记1 - 快速体验
又重新开始了scala的学习,因为中断了太长时间,所以这次还得从零开始.学习的过程就记录在这个博客上了. 这次学习的教程是<scala程序设计 java虚拟机多核编程实战>,我在多看上买了 ...
随机推荐
- Spoken English Practice( Nobody have the guts to tell Paul what a mistake he was taking.(call,come,gut,fortune,when it comes to))
音标复习 绿色:连读: 红色:略读: 蓝色:浊化: 橙色:弱读 口语蜕变(2017/6/24) If your ...
- 你不知道的Javascript(上卷)读书笔记之三 ---- 函数作用域与块作用域
1. 函数中的作用域 函数作用域的含义是指属于这个函数的全部变量都可以在整个函数范围内使用以及复用 2. 隐藏内部实现 函数经常使用于隐藏”内部实现”,可以把变量和函数包裹在一个函数的作用域中,然后用 ...
- 超过70亿条数据的mysql 去重
1.数据库层面: 2.业务层面:接口去重.浏览器显示端去重:
- tomcat和jboss的区别
1. Tomcat是Apache鼎力支持的Java Web应用服务器(注:servlet容器),由于它优秀的稳定性以及丰富的文档资料,广泛的使用人群,从而在开源领域受到最广泛的青睐. 2. Jboss ...
- Redis与Memcached的比较(转)
原文:http://blog.nosqlfan.com/html/3729.html 这两年Redis火得可以,Redis也常常被当作Memcached的挑战者被提到桌面上来.关于Redis与Memc ...
- 我的Android进阶之旅------>Android关于HttpsURLConnection一个忽略Https证书是否正确的Https请求工具类
下面是一个Android HttpsURLConnection忽略Https证书是否正确的Https请求工具类,不需要验证服务器端证书是否正确,也不需要验证服务器证书中的域名是否有效. (PS:建议下 ...
- 一 创建github账号以及上传工程到github
第一步:安装git. apt-get install git 第二步:配置用户名和密码: git config –global user.name “XXX” git config –global u ...
- [Mysql ]TIME ZONE
mysql的时间相关的类型如下: 1. timestamp 时区敏感的 2. date 非时区敏感 3. datetime 非时区敏感 4. time 非时区敏感
- 利用反射快速给Model实体赋值
试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有120多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ...
- python s13 day04
1.1 all() 和 any( ) all() any() 0,None,"", [], (),{} #布尔值为0的 列举,None ,空列表,空元祖,空. print( ...