美文网首页
使用控制抽象函数(贷出模式loan pattern)

使用控制抽象函数(贷出模式loan pattern)

作者: no0one | 来源:发表于2019-08-28 09:59 被阅读0次

(Scala编程P.173)打开某个资源,对它进行操作,然后关闭这个资源。可以用类似如下的方法,将这个模式捕获成一个控制抽象,withPrintWriter打开某个资源并将这个资源“贷出”给函数op

def withPrintWriter(file: File, op: PrintWriter => Unit): Unit = {
  val writer = new PrintWriter(file)
  try {
    op(writer)
  } finally {
    writer.close()
  }
}

withPrintWriter(
  new File("date.txt"),
  writer => writer.println(new java.util.Date)
)

实践:

读取配置文件,都是打开文件,读取配置文件内容,可以考虑贷出模式

ReadConfigFile.scala

import com.typesafe.config.{Config, ConfigFactory}

import scala.reflect.ClassTag

class ReadConfigFile[T:ClassTag](clz: Class[T]){
  def read(fileName: String)(fromConfig: Config => T): T = {  //柯里化
    val file = new File(fileName)
    if (!file.exists())  clz.newInstance()//不能直接new T(),scala不能识别,需要通过ClassTag,增加Class[T]入参用,newInstance来构造一个新的对象,而且这个对象不能带入参。
    else {
      println(s"path = $fileName")
      try {
        val conf:Config = ConfigFactory.parseFile(file).withFallback(ConfigFactory.load())
        fromConfig(conf)
      } catch {
        case ex: Exception => clz.newInstance()
      }
    }
  }
}

这里用到了泛型类,可以传入对于任何需要读取配置参数类,将读取文件的方法通过fromConfig函数值传进来

PersonConfig.scala

class PersonConfig{
  var name: String = ""
  var age: Int = 0

  override def toString: String = {
    "name=" + name + " age=" + age
  }
}

object PersonConfig{
  def createPersonConfig(config: Config): PersonConfig= {
    val PersonConfig= new PersonConfig
    PersonConfig.name = config.getString("name ")
    PersonConfig.age= config.getInt("age")
    PersonConfig
  }
}

ITDepartmentConfig.scala

class ITDepartmentConfigextends ReadConfigFile(classOf[PersonConfig]){
  private val personConfig: PersonConfig= {
    read("person.conf") { config =>
      PersonConfig.createServerConfig(config.getConfig("person_config"))
    }//传入读取文件的方法并生成相关的对象
  }

  def person: PersonConfig= personConfig
}

**Test.scala**
object Test {
  def main(args: Array[String]): Unit = {
    val itDepartmentConfig= new ITDepartmentConfig
    println(itDepartmentConfig.person.toString)
  }
}

上这里提到了不能直接new T()的问题,可以通过多加一个传名参数来解决,就不需要使用ClassTag,使用ClassTag导致构造函数中不可以带入参。方法如下:

class ReadConfigFile[T]{
  def read(fileName: String)(fromConfig: Config => T)(emptyObject: => T): T = {
    val file = new File(fileName)
    if (!file.exists())  emptyObject
    else {
      println(s" path = $fileName ")
      try {
        val conf:Config = ConfigFactory.parseFile(file).withFallback(ConfigFactory.load())
        fromConfig(conf)
      } catch {
        case ex: Exception => emptyObject
      }
    }
  }
}

调用时

class RESTServerConfig extends ReadConfigFile[ServerConfig] with Subject {
  private val serverConfig: ServerConfig = {
    read(FileUtil.getConfigPath + "rest-server.conf") { config =>
      ServerConfig.createServerConfig(config.getConfig("rest_server_config"))
    }(new ServerConfig())
  }

  def server: ServerConfig = serverConfig
}

相关文章

网友评论

      本文标题:使用控制抽象函数(贷出模式loan pattern)

      本文链接:https://www.haomeiwen.com/subject/atxpectx.html