【问题标题】:Encapsulating related fields into a companion object/class and avoiding duplication将相关字段封装到伴随对象/类中并避免重复
【发布时间】:2013-04-03 14:34:14
【问题描述】:

我的应用程序使用一个属性文件来加载多个属性。

应用程序的每个实例都有 3 个与环境相关的参数 - 其中一个是属性,另外两个是基于它计算的。

class Environment(val properties: Properties) {
    val dbUrl = valueOrError("db.url")
    val host = valueOrError("host")
    //... 

    val environmentFlag = valueOrError("env.flag") 
    val environmentToken = environmentFlag match {
        case "live" => "L"
        case "staging" => "S"
        case "test" => "T"
    val environmentUrlPrefix = environmentFlag match {
        case "live" => ""
        case "staging" => "staging-"
        case "test" => "test"
    }       

}

在我看来,这 3 个 environment* 属性应该以某种方式封装。

我将所寻求的抽象称为 Discriminator,因为它用于区分 3 种(目前)环境类型。由于在一个正在运行的应用程序中,只有一组这样的 environment* 属性,因此我将其实现为 object:

class Environment(val properties: Properties) { 
    val dbUrl ... 

    object Discriminator {
        val flag = valueOrError("env.flag")
        val token = flag match {
            case "live" => "L"
            case "staging" => "S"
            case "test" => "T"
        val urlPrefix = flag match {
            case "live" => ""
            case "staging"=> "staging-"
            case "test" => "test-"
        }
     }
}

我可以致电:environment.Discriminator.urlPrefix,这很好,但我该如何改进代码?如何摆脱重复的match?
现在感觉live 的token 和urlPrefix 的值应该一起存在(staging 的值也应该这样)——有点像作为鉴别器类的一个实例的一部分。

abstract class Discriminator(val flag = valueOrError("env.flag"), 
                             val token: String
                             val urlPrefix: String)

由于我仍然想使用environment.Discriminator.urlPrefix,我仍然需要Discriminator(现在)伴生对象。

但我被困在这里 - 我不知道如何结合这些概念。

显然,我必须根据具体的 flag 字段为自己创建 3 个鉴别器实例,但是如何创建?如何调用构造函数 - 根据第一个参数(所有实例共有)传递最后两个参数?

一旦我有了这个,如何将三个实例与鉴别器伴生对象连接起来,以便我可以使用environment.Discriminator.urlPrefix?

【问题讨论】:

    标签: oop scala encapsulation code-duplication companion-object


    【解决方案1】:

    您可以像这样同时初始化token 和urlPrefix:

    val (token, urlPrefix) = flag match {
      case "live" => ("L", "")
      case "staging" => ("S", "staging-")
      case "test" => ("T", "test-")
    }
    

    【讨论】:

    • 是的!我正在努力从对创建案例对象(例如:Discriminator(flag match {.. => ("L", "').. }),而实际上我根本不需要任何显式对象。谢谢!
    【解决方案2】:

    为什么不替换这个:

       val token = flag match {
            case "live" => "L"
            ....
        val urlPrefix = flag match {
            case "live" => ""
            .....
    

    返回一个元组?例如

       val tokens = flag match {
            case "live" => ("L", "")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-10-08
      • 2017-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-02
      • 1970-01-01
      相关资源
      最近更新 更多