Scala 案例 class 丰富了抽象组件(蛋糕模式)
Scala case class enriched with abstract component (Cake Pattern)
我们使用蛋糕模式来抽象具有自类型注释的组件(DB、Mock),这些组件在顶层调用时被注入。
在一种情况下 class 我们希望能够通过扩展共同特征来丰富它的行为。但是如果我们想让这个caseclass调用一个抽象组件怎么办呢?
将案例 class 重构为抽象将删除应用、取消应用、复制的所有实现...我们需要在数据库和模型之间进行映射的事情(例如使用 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)
}
}
}
关于如何在不重新实现所有案例 class 样板的情况下如何做到这一点的想法?在具有 case class 模式匹配的资源伴随对象中添加 getAccount 将无法解决问题
我们选择实现一个 ResourceService,根据资源类型,return 资源所属的帐户。
这是特征组件:
trait ResourceServiceComponent {
val resourceService: ResourceService
trait ResourceService {
def getAccount(resource: Resource): Future[Account] = {
resource match {
case plant: Plant => blockDB.getAccount(plant.blockId)
case ...
}
}
}
}
我们使用蛋糕模式来抽象具有自类型注释的组件(DB、Mock),这些组件在顶层调用时被注入。
在一种情况下 class 我们希望能够通过扩展共同特征来丰富它的行为。但是如果我们想让这个caseclass调用一个抽象组件怎么办呢? 将案例 class 重构为抽象将删除应用、取消应用、复制的所有实现...我们需要在数据库和模型之间进行映射的事情(例如使用 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)
}
}
}
关于如何在不重新实现所有案例 class 样板的情况下如何做到这一点的想法?在具有 case class 模式匹配的资源伴随对象中添加 getAccount 将无法解决问题
我们选择实现一个 ResourceService,根据资源类型,return 资源所属的帐户。
这是特征组件:
trait ResourceServiceComponent {
val resourceService: ResourceService
trait ResourceService {
def getAccount(resource: Resource): Future[Account] = {
resource match {
case plant: Plant => blockDB.getAccount(plant.blockId)
case ...
}
}
}
}