Scala Pattern 之 Loan Pattern

本文介绍Scala中的LoanPattern,一种用于资源管理和使用的模式。通过定义泛型方法use,可以在使用完毕后自动关闭资源,提高代码的简洁性和可读性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Scala Pattern 之 Loan Pattern


Loan Pattern从字面上的来看,意思就是, “ ”贷给“ ”某样东西, 用完后还得还“ ”。 在Scala里面,你可以使用这种模式来实现相应资源的管理和使用。这跟Spring框架里JdbcTemplate+相应Callback的实践很相似, 不过, 在表达上面, 用Scala要更简洁,明确。

因为Java7之后才能用到Closure, 所以,在此之前,Spring给出的Template Method Pattern + Callback的最佳实践, 是我们可以优雅的解决资源管理和使用的最好方式。Java7就好像这个问题的一个分水岭, 有了Java7,你会发现针对这个问题的支持变得那么资源充沛, 因为,Java7里有了Closure,我们再也不用求助于Callback接口和相应的匿名内部类了, 并且, Java7里还专门针对资源的自动管理提供了一种语法糖(Syntactic Sugar), 使得这一问题的表达更简单, 例如:

try (BufferedReader br = new BufferedReader(new FileReader(path)) {  
   return br.readLine();  
}  
 

不过, 说那么多,现在,我们还是得望“Java7 ”止渴,所以,不妨先看看Scala是如何来解决这一问题的。

如果要用Scala来解决这一问题,我们可以定义一个object如下:

package cn.spring21.scalapattern

import java.io.Reader

object LoanPattern {

    def use[T <: Reader,O](resource:T)(func:T=>O){
        try{
            func(resource)
        }finally{
            resource.close
        }
    }
}
 

在LoanPattern对象中,我们定义了一个use方法, 它接受2个参数:

  1. 第一个参数resource类型为T;

  2. 第二个参数func为一个函数定义, 表明它接受一个T类型的参数,返回一个O类型的返回值;

这里有点儿“拗口 ”的就是方法定义use后面的[]中定义的内容, []用来声明参数类型, 类似于Java5之后引入的泛型(Generics)的概念, T <: Reader简单来讲,其实就是说, T类型是java.io.Reader的某种子类型, 从而, use方法定义中就可以把这个类型“ ”给接受T类型参数的函数, 并在函数使用完T类型的资源之后, 关闭它。

有了以上定义之后,我们就可以开始“ ”了, 我们可以如下的形式使用它:

import LoanPattern._
import java.io._		
		
use(new BufferedReader(new FileReader("E:/MyNote.txt"))){
    reader=>
    var line:String = null
    line = reader.readLine
    while(line !=null)
    {
        println(line)
        line = reader.readLine
    }
}
 

import LoanPattern._类似于Java5的static import, 有了它,我们才可以如上的形式来使用use方法,这让它看起来像是语言固有的语法结构, 但实际上,在Scala中,它只是一种常见的对象方法定义而已。use接受2个参数, 第一个参数,我们传入了一个BufferedReader, 第二个则是一个function定义, 我们通过reader => 的形式明确指定了这个function接受的参数名称,然后就可以使用它来读取任何文件了。

Tip

看到这里,有人可能要骂了,这种烂代码也好意思拿出来? 呵呵,实际上, 这里更多的是为了演示的目的, 如果只是简单的读取文件内容并打印,在Scala里面其实更简洁,也更常用的代码是:

println(scala.io.Source.fromFile("E:/MyNote.txt","UTF-8").getLines.mkString)
 

仅此一句话而已。

 

use的定义现在只能负责Reader及其子类相关的资源管理, 但我们可以扩展它,让它变得更加通用,例如:

def use2[T <: {def close();},O](resource:T)(func:T=>O){
    try{
        func(resource)
    }finally{
        resource.close
    }
}
 

use2的定义比use要更进一步, 它可以接受任何定义了close()方法的类型的实例作为资源参数,比如InputStream, OutputStream, Reader, Writer等等,甚至Connection,只要这种类型定义了close()方法就行, 所以,有了它, 剩下的也只是根据情况提供相应的函数定义而已了:

val conn:Connection = dataSource.getConnection
use2(conn){
	val stat:Statement = conn.createStatement
	use2(stat){
		val rs:ResultSet = stat.executeQuery("...")
		use2(rs){
			...// retrieve result data with rs
		}
	}
}
 

简单吧?强大吧?

Tip

Lift框架的作者给出了一条提炼Scala代码的建议,就是尽量减少代码的行数,所以, use或者use2方法可以进一步精炼一下:

def use[T<: Reader,O](resource:T)(func:T=>O){
    try{func(resource)}finally{resource.close}
}
 

甚至于:

def use[T<: Reader,O](resource:T)(func:T=>O) = try{func(resource)}finally{resource.close}
 

当然啦, 应该以尽量不影响代码的可读性为准,也不要让精简后的代码让人阅读起来很费劲为好。

 

Loan Pattern其实是很常见的Pattern, 本文主要关注如何用Scala来表达这一Pattern, 用Ruby之类支持Block/Lambda结构的动态语言当然也可以很容易的表达, 但这已经不是本文要阐述的了。

资源下载链接为: https://pan.quark.cn/s/22ca96b7bd39 在当今的软件开发领域,自动化构建与发布是提升开发效率和项目质量的关键环节。Jenkins Pipeline作为一种强大的自动化工具,能够有效助力Java项目的快速构建、测试及部署。本文将详细介绍如何利用Jenkins Pipeline实现Java项目的自动化构建与发布。 Jenkins Pipeline简介 Jenkins Pipeline是运行在Jenkins上的一套工作流框架,它将原本分散在单个或多个节点上独立运行的任务串联起来,实现复杂流程的编排与可视化。它是Jenkins 2.X的核心特性之一,推动了Jenkins从持续集成(CI)向持续交付(CD)及DevOps的转变。 创建Pipeline项目 要使用Jenkins Pipeline自动化构建发布Java项目,首先需要创建Pipeline项目。具体步骤如下: 登录Jenkins,点击“新建项”,选择“Pipeline”。 输入项目名称和描述,点击“确定”。 在Pipeline脚本中定义项目字典、发版脚本和预发布脚本。 编写Pipeline脚本 Pipeline脚本是Jenkins Pipeline的核心,用于定义自动化构建和发布的流程。以下是一个简单的Pipeline脚本示例: 在上述脚本中,定义了四个阶段:Checkout、Build、Push package和Deploy/Rollback。每个阶段都可以根据实际需求进行配置和调整。 通过Jenkins Pipeline自动化构建发布Java项目,可以显著提升开发效率和项目质量。借助Pipeline,我们能够轻松实现自动化构建、测试和部署,从而提高项目的整体质量和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值