Scala中的借贷者模式

Scala中的借贷者模式,scala,Scala,演示借贷者模式: 用法示例: readFile(new java.io.File("test.txt")) { input => println(input.readByte) } 这段代码看起来简单明了。在Scala中,借贷者模式的“反模式”是什么,这样我就知道如何避免它了?请确保您计算的内容都经过认真评估,不再依赖于资源。Scala使惰性计算变得相当容易。例如,如果您以这种方式包装scala.io.Source.fromFile,您可以尝试 readFile("test.txt

演示借贷者模式:

用法示例:

readFile(new java.io.File("test.txt")) { input =>
   println(input.readByte)
}

这段代码看起来简单明了。在Scala中,借贷者模式的“反模式”是什么,这样我就知道如何避免它了?

请确保您计算的内容都经过认真评估,不再依赖于资源。Scala使惰性计算变得相当容易。例如,如果您以这种方式包装scala.io.Source.fromFile,您可以尝试

readFile("test.txt")(_.getLines)
不幸的是,这不起作用,因为
getLines
是惰性的(返回一个迭代器)。Scala没有任何好的方法来指示哪些方法是懒惰的,哪些不是。因此,你只需要知道(医生会告诉你),你必须在返回之前实际完成工作:

readFile("test.txt")(_.getLines.toVector)

总的来说,这是一个非常有用的模式。只需确保在退出块之前完成对资源的所有访问(因此,没有未完成的未来,没有依赖于资源的惰性VAL,没有迭代器,没有返回资源本身,没有未被完全读取的流,等等;当然,如果它们不依赖于打开的资源,而只依赖于基于资源的某个完全计算的数量,那么这些事情都是可以的).

对于借用模式,重要的是要知道实际调用借用资源的代码的“位”何时将使用它

如果希望从贷款模式返回期货,我建议不要在传递给贷款模式函数的函数中创建期货

不要写

readFile("text.file")(future { doSomething })
但要做到:

future { readFile("text.file")( doSomething ) }
我通常会定义两种贷款模式函数:同步和异步

所以在你的情况下,我会:

def asyncReadFile[T](f: File)(handler: FileInputStream => T): Future[T] = {
  future{
    readFile(f)(handler)
  }
}

这样可以避免调用关闭的资源。并且可以重用已经测试过的、希望是正确的同步函数代码。

注意,它在
Future
上失败:
readFile(…){in=>Future{println(in.readByte)}
in.readByte
可以在
关闭后执行。有趣的是,为了避免这个问题,只需在这个模式中使用
Future
?也不要在
中返回
,或者在
中可能包含
的任何内容:
读取文件(…){in=>b:Byte=>input.readByte+b}
。(请注意,FileInputStream中没有方法
readByte
)。在中有此模式的实现。从Scala 2.13开始,无需编写自己的贷款模式实现,因为有一个实用程序.def readFile[T](f:File)(handler:FileInputStream=>T):T=Using.resource(new FileInputStream(f))(handler)
def asyncReadFile[T](f: File)(handler: FileInputStream => T): Future[T] = {
  future{
    readFile(f)(handler)
  }
}