0

在我在 Internet 上找到的所有与 Cake 模式相关的文章中,我看到了单级依赖关系,这对我来说很清楚。

但是当我开始使用它时,我遇到了一个问题,我不能只在高级课程中使用服务,我需要在多个地方混合使用它。

例如,如果我有一个服务并且该服务与一组其他服务一起使用,并且该组中的每个服务都使用一个数据库,那么我尝试不从这组低级服务中直接访问数据库。我只在高级服务中进行了所有数据库查询。但在某些情况下很难。

通过这个例子,问题可能会更清楚:

trait DatabaseServiceComponent{
      val databaseService: DatabaseService
      trait DatabaseService{
        def getSomeData(id: Int, tableName: String): List[String]
        def getFriends(id: Int): List[Int]

  }
}

trait DatabaseServiceComponentImpl extends DatabaseServiceComponent{
  val databaseService: DatabaseService = new DatabaseServiceImpl
  class  DatabaseServiceImpl extends DatabaseService{
    def getSomeData(id: Int,  tableName: String): List[String] = ???
    def getFriends(id: Int): List[Int] = ???
  }
}

trait Scoring { this: DatabaseServiceComponent =>
  def importantValues: Set[String]
  val tableName: String
  def getScore(id: Int): Double = databaseService.getSomeData(id, tableName).count(importantValues)
}

class Scoring1 extends Scoring{this: DatabaseServiceComponent =>
  val tableName: String = "s1"
  override def importantValues: Set[String] = Set("a", "b")
}

class Scoring2 extends Scoring{this: DatabaseServiceComponent =>
  val tableName: String = "s2"
  override def importantValues: Set[String] = Set("foo", "bar")
}

class Scoring3 extends Scoring{this: DatabaseServiceComponent =>
  val tableName: String = "s3"
  override def importantValues: Set[String] = Set("1", "2")
}

// How to implement this correctly?
trait Scoring2FriendsAverage {this: DatabaseServiceComponent =>
  val scoring2: Scoring2
  def getScore(id: Int):Double ={
    val scores = databaseService.getFriends(id).map(scoring2.getScore)
    scores.size / scores.sum
  }
}


object FriendsScoringProcessor{

  val scoring2Friends = new Scoring2FriendsAverage with DatabaseServiceComponentImpl{
    val scoring2 = new Scoring2 with DatabaseServiceComponentImpl // I don't like that I have to mix the implementation of a service again
  }

  def printScores(id: Int): Unit = {
    val score = scoring2Friends.getScore(id)
    println(score)
  }

}

我有一组评分,每个评分都使用一个数据库。我有一个 FriendsScoring,它使用使用数据库的评分之一。我希望能够仅将数据库实现与 FriendsScoring 混合,并且不要在较低级别的服务中复制它。

我看到一个好的(可能是)解决方案是通过隐式构造函数参数为低级服务提供实现。

4

1 回答 1

2

它看起来像是蛋糕模式组件和服务的混合级别。

如果我们Scoring在服务层使用,那么它不应该出现在蛋糕模式级别。

您可能希望Scoring像对数据库所做的那样,在每个级别上拆分为两个嵌套特征:

trait ScoringComponent {this: DatabaseServiceComponent =>

  trait ScoringService {
    def getScore(id: Int): Double = 
      databaseService.getSomeData(id, tableName).
        count(importantValues)
  }
}

ScoringService然后混合所需的依赖项后就可以使用了。

于 2017-06-16T08:29:59.253 回答