再一次读到 Scala 中的“贷出模式(Loan Pattern)”这个术语,这才比上次稍了解一些。我的理解,此一模式大概是说,对于那些资源密集(resource-intensive)型对象的使用应该使用这一模式。
使用这一模式的原因是,既然资源集中在一个对象中,那么用户代码就不能一直保持着获得的所有资源,而应该在需要时就向资源供给方进行借贷,使用完毕之后立即归还。
此外,Scala 中将函数也是对象,可以像参数那样传递给另一个函数的特征使得贷出模式更加有意义。客户代码借贷了所需的资源,接下来如何使用这些资源以完成特定的任务则由客户决定。就像我们向银行贷款,这些钱的具体用途是客户决定,也是客户才明确的。
对于此类资源,有数据库连接、IO操作等,这些是我们用完则务必立即释放的资源。而且,资源使用完毕业意味着将被自动回收,我们不必操心资源回收的过程。
下面是一个 Scala 脚本代码,客户提供一个文件名,利用writeFile 方法中能够一个向该文件写入内容的 PrintWriter 对象。而具体如何使用这个 PrintWriter 对象则由用户确定,使用完则由自动释放。
- def writeFile(fileName: File)(operation: PrintWriter => Unit) {
- val writer = new PrintWriter(fileName) // 贷出资源writer
- try{
- operation(pw) // 客户使用资源
- }finally {
- writer.close() // 用完则释放被回收
- }
- }
上面 writeFile 方法的定义使用到了 Scala 中的curring技巧,所以才会看到 writeFile 定义之后有两个参数列表(即两个小括号对),后面的参数 operation 用于传入客户具体想要的操作(即怎么使用资源)。
客户代码如下:
- val file = new File("test.txt")
- writeFile(file) {
- // 使用资源的具体操作
- writer => writer.println("haolloyin ...\r\n" +
- new java.util.Date())
- }
执行该脚本,会发现在当前目录下生成一个 test.txt 文件,里面的内容如下:
- haolloyin...
- Fri Sep 03 22:44:18 CST 2010
在这个例子中,客户对资源的使用完全是自定义的,如上面的writer => writer.println(…) 所示。但是有时候我们会遇到一些本身已经预定义好所具备操作的资源,那么此时可以结合 Singleton Object 单例对象的使用特点对其伴生类所代表的资源进行创建和使用。
同时使用资源类与其单例对象的用意在于,确保该资源只能通过伴生对象进行合法访问,控制好资源的客户源的合法性。这在《Scala 铅笔书》中有下面这个例子,我把代码拷贝并注释如下:
- // 主构造器私有,限制其对象(资源)的创建范围
- 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.use { resource =>
- resource.op1
- resource.op2
- resource.op3
- resource.op1 // 任意的操作调用序列
- }
程序输出:
- Starting transaction...
- Operation 1
- Operation 2
- Operation 3
- Operation 1
- Ending transaction...
转载于:https://blog.51cto.com/haolloyin/387138