gpt4 book ai didi

Scala - 如何避免对象工厂的 if/else 条件

转载 作者:行者123 更新时间:2023-12-04 15:30:34 25 4
gpt4 key购买 nike

我正在尝试解决以下问题。问题

  • 我必须编写一个复制方法 来从一个文件系统复制到另一个文件系统。 (即本地到 hdfs,s3 到 s3,以及以后的一些)。
  • 此文件系统(本地、s3、hdfs)将来可能会增加,操作(复制、移动、删除)也会增加
  • 有些操作是跨文件系统的(即复制、移动)有些不是,即(删除、列出、查找)
  • 我有一个属性文件,其中包含源位置和目标位置,以及一些其他字段(即计数),可帮助我了解将文件复制到何处。

I tried to solve the problem using Factory in following way, however it's still not able to solve Cross Platform action problem. And code doesn't look elegant.

实现

abstract class FileSystem(propFileURI: String) {
def moveFile(): Unit
}

object FileSystem {

private class HDFSystem(propFileURI: String) extends FileSystem(propFileURI) {
override def moveFile(): Unit = {
println(" HDFS move file")
}
}

private class S3System(propFileURI: String) extends FileSystem(propFileURI) {
override def moveFile(): Unit = {
println("S3 Move File ")
}
}

def apply(propFileURI: String): Option[FileSystem] = {
val properties: Properties = new Properties()

val source = Source.fromFile( System.getProperty("user.dir")+"\\src\\main\\resources\\"+propFileURI).reader
properties.load(source)
val srcPath = properties.getProperty("srcPath")
val destPath = properties.getProperty("destPath")

if (destPath.contains("hdfs")){
Some(new HDFSystem(propFileURI))
}
if (srcPath.contains("s3") && destPath.contains("s3")){
Some(new S3System(propFileURI))
}else{
None
}

}

def main(args: Array[String]): Unit = {
val obj = FileSystem("test.properties")
obj match {
case Some(test) => test.moveFile()
case None => println("None returned")
}
}
}

问题:

  1. moveFile 的当前实现仅处理 s3->s3hdfs->hdfs。如何为 local->hdfslocal->s3

  2. 实现相同的方法
  3. 如何将HDFSystemS3System 移动到单独的文件?

  4. 如何在apply方法中避免if/else

最佳答案

您可以用模式匹配替换if-else。但是,这不仅仅是 if-else 语句,对吧?所以可以这样写:


sealed abstract class FileSystem(propFileURI: String) {
def moveFile(): Unit
}

case class HDFSystem(propFileURI: String) extends FileSystem(propFileURI) {
override def moveFile(): Unit =
println(" HDFS move file")
}

case class S3System(propFileURI: String) extends FileSystem(propFileURI) {
override def moveFile(): Unit =
println("S3 Move File ")
}
case class MoveFile(hdfs: Option[HDFSystem] = None, s3: Option[S3System] = None)

object FileSystem {

def apply(propFileURI: String): MoveFile = {
val properties: Properties = new Properties()
val source = Source.fromFile(System.getProperty("user.dir") + "\\src\\main\\resources\\" + propFileURI).reader
properties.load(source)

val srcPath = Option(properties.getProperty("srcPath")).fold(false)(_.contains("hdfs"))
val destPath = Option(properties.getProperty("destPath")).fold(false)(_.contains("s3"))

(destPath, srcPath) match {
case (true, true) =>
MoveFile(
hdfs = Option(HDFSystem(propFileURI)),
s3 = Option(S3System(propFileURI))
)
case (false, true) =>
MoveFile(s3 = Option(S3System(propFileURI)))
case (true, false) =>
MoveFile(hdfs = Option(HDFSystem(propFileURI)))
case _ =>
MoveFile()
}
}
}

object TestObj {

def main(args: Array[String]): Unit = {
val obj = FileSystem("test.properties")
(obj.hdfs, obj.s3) match {
case (Some(hdfs), _) => hdfs.moveFile()
case (_, Some(s3)) => s3.moveFile()
case (_, _) => println("None returned")
}
}
}

老实说,我不喜欢上面的实现,并针对以下用例进行了稍微修改。您可以将它们用作没有 MoveFile 包装器的 ADT:


def testMethod(fs: FileSystem): Unit = {
fs.moveFile()
}

def main(args: Array[String]): Unit = {
// You can have a logic here for which way to go
val obj = S3System("test.properties")
testMethod(obj)
val obj1 = HDFSystem("test.properties")
testMethod(obj1)
}

在这种情况下,您可以完全删除 FileSystem 对象。如果你想要一些路径检查器,你可以将它们放在每个 sub-type 中。 HdfsSystemS3Sytem 应该实现moveFile 方法

关于Scala - 如何避免对象工厂的 if/else 条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61315875/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com