scala - Scala - 如何避免对象工厂的 if/else 条件
问题描述
我正在尝试解决以下问题。 问题
- 我必须写一个
copy method
从一个文件系统复制到另一个文件系统。(即本地到 hdfs,s3 到 s3,以及稍后更多)。 - 此文件系统(本地、s3、hdfs)将来可能会增加,操作(复制、移动、删除)也会增加
- 有些操作是跨文件系统的(即复制、移动)有些不是跨文件系统(删除、列表、查找)
- 我有一个属性文件,其中包含源位置和目标位置,以及一些其他字段(即计数),它们可以帮助我了解复制文件的位置。
我尝试通过以下方式使用 Factory 解决问题,但仍然无法解决跨平台操作问题。而且代码看起来并不优雅。
执行
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")
}
}
}
问题:
当前
moveFile
仅执行句柄s3->s3
和hdfs->hdfs
. 如何为local->hdfs
和实现相同的方法local->s3
如何移动
HDFSystem
和S3System
分离文件?if/else
方法上如何避免apply
?
解决方案
您可以替换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
s. HdfsSystem
并且S3Sytem
应该实现moveFile
方法
推荐阅读
- python - 用于注册和登录的 Django 不同的 USERNAME 字段
- shell - 有没有办法在 Ubuntu WSL 中使用“Ctrl-Shift-(箭头键)”突出显示整个单词?
- apache - 如何在同一个 apache 网络服务器上运行 mod-mono 和 php
- continuous-integration - GitLab CI 登录到没有 DinD 的私人仓库
- html - 如何在 Angular 中动态更改环境变量?
- javascript - 未从 omdbapi.com 获取数据
- python - 根据一帧的行值和另一帧的列值合并两个数据帧
- javascript - 一起注释掉 HTML、CSS、Javascript 代码
- sql-server - Entity Framework 复杂搜索功能
- android - 我正在为 IOS 和 android 移动应用程序创建测试用例脚本