Фабрика с сопутствующим объектом, где каждый тип объекта принимает общий параметр - PullRequest
1 голос
/ 21 января 2020

У меня есть такой класс -

class Cache (
  tableName: String,
  TTL: Int) {
  // Creates a cache
}

У меня есть объект-компаньон, который возвращает различные типы кэшей. У него есть функции, которые требуют базового имени таблицы и могут создавать кеш.

object Cache {
   def getOpsCache(baseTableName: String): Cache = {
    new Cache(s"baseTableName_ops", OpsTTL);
  }

  def getSnapshotCache(baseTableName: String): Cache = {
    new Cache(s"baseTableName_snaps", SnapshotTTL);
  }

  def getMetadataCache(baseTableName: String): Cache = {
    new Cache(s"baseTableName_metadata", MetadataTTL);
  }
}

Объект делает еще несколько вещей, а класс Cache имеет больше параметров, что делает его полезным иметь вспомогательный объект создавать различные типы Cache с. Параметр baseTableName одинаков для всех кэшей. Есть ли способ, которым я могу передать этот параметр только один раз, а затем просто вызывать функции для получения различных типов кэшей?

Альтернативой этому является создание фабричного класса и передача параметра baseTableName в конструктор а затем вызвать функции. Но мне интересно, можно ли это сделать каким-либо образом с помощью объекта Companion.

Ответы [ 2 ]

3 голосов
/ 21 января 2020

Рассмотрим создание алгебраического типа данных c, например

sealed abstract class Cache(tablePostfix: String, ttl: Int) {
  val tableName = s"baseTableName_$tablePostfix"
}
case object OpsCache extends Cache("ops", 60)
case object SnapshotCache extends Cache("snaps", 120)
case object MetadataCache extends Cache("metadata", 180)

OpsCache.tableName // res0: String = baseTableName_ops
3 голосов
/ 21 января 2020

Самый простой способ - это поместить вашу фабрику в case class:

case class CacheFactory(baseTableName: String) {

  lazy val getOpsCache: Cache = 
     Cache(s"baseTableName_ops", OpsTTL)

  lazy val getSnapshotCache =
     Cache(s"baseTableName_snaps", SnapshotTTL)

  lazy val getMetadataCache =
    Cache(s"baseTableName_metadata", MetadataTTL) 
}

Как мне нравится case classes Я также изменил ваш кэш на case class:

case class Cache(tableName: String, TTL: Int)

Как видите, я скорректировал ваш Java код для исправления Scala код.

Если вы хотите поместить его в companion object, вы можете использовать implicits, например:

object Cache {

  def getOpsCache(implicit baseTableName: String): Cache = 
     Cache(s"baseTableName_ops", OpsTTL)

  def getSnapshotCache(implicit baseTableName: String) =
     Cache(s"baseTableName_snaps", SnapshotTTL)

  def getMetadataCache(implicit baseTableName: String) =
    Cache(s"baseTableName_metadata", MetadataTTL) 
}

Тогда ваш клиент будет выглядеть так:

implicit val baseTableName: String = "baseName"

cache.getSnapshotCache
cache.getMetadataCache
...