Scala案例类丰富了抽象组件(Cake Pattern)

时间:2016-11-21 13:48:16

标签: scala design-patterns slick-3.0

我们使用蛋糕模式来抽象具有自我类型注释的组件(DB,Mock),它们是在顶级调用中注入的。

在一个案例类中,我们希望能够通过扩展共同特征来丰富它的行为。但是如果我们希望这个case类调用一个抽象组件怎么做呢? 将case类重构为abstract将删除apply,unapply,copy ...的所有实现。我们需要在数据库和模型之间进行映射(例如使用Slick)。

这是一个例子,表示作为资源拥有的一些块中的植物:

trait Resource {
  def getAccount: Future[Account]
}

case class Account(id: Int)

case class Block(id: Int, name:String, accountId: Int) extends Resource

case class Plant(id: Int, name: String, blockId: Int) extends Resource {
  this: PlantDBComponent => 

 override def getAccount: Future[Account] = plantDB.getAccount(this)

}

trait PlantDBComponent {
  def plantDB: PlantDB

  trait PlantDB {
    def getAccount(plant: Plant): Future[Account]
  }
}

trait SlickPlantDBComponent {
  def blockDB = SlickPlantDB()

  trait SlickPlantDB extends PlantDB {
    def getAccount(block: Block): Future[Account] = {
      val q = for {
        block <- BlockTable if block.id === plant.blockId
        account <- AccountTable if account.id === block.accountId
      } yield account

      db.run(q.result.head)
    }
  }
}

如果没有重新实现所有案例类样板,怎么做?在具有案例类模式匹配的资源伴随对象中添加getAccount将无法解决问题

1 个答案:

答案 0 :(得分:0)

我们选择实现一个ResourceService,根据资源类型,返回资源所属的帐户。

这是特质成分:

trait ResourceServiceComponent {

  val resourceService: ResourceService

  trait ResourceService {
    def getAccount(resource: Resource): Future[Account] = {
      resource match {
        case plant: Plant => blockDB.getAccount(plant.blockId)
        case ...
      }
    }
  }
}