2017-06-16 71 views
0

在Internet上发现的所有与Cake patter相关的文章中,我都看到了单个级别的依赖关系,这对我来说很清楚。如何避免重复执行与蛋糕模式的混合

但是当我开始使用它时,我遇到了一个问题,我不能仅在高级别类中使用服务,而且我需要将它混合到多个位置。

例如,如果我有一个服务,并且此服务与其他一组服务一起工作,并且此组中的每个服务都使用一个数据库,我尝试不直接访问来自这组低级服务的数据库。我仅在高级服务中完成所有数据库查询。 但在某些情况下很困难。

可能问题会随着这个例子更清楚:

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,并且不要在较低级别的服务中复制它。

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

回答

2

它看起来像蛋糕模式组件和服务的混合水平。

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

您可能需要像你这样的数据库,以Scoring分成两个嵌套的特质在每个级别:

trait ScoringComponent {this: DatabaseServiceComponent => 

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

然后你就可以混合所需要的依赖后使用ScoringService