蛋糕模式嵌套特征

时间:2014-03-23 21:36:06

标签: scala cake-pattern

为什么每个人都使用这种形式的定义:

trait UserServiceComponent {
  def userService: UserService
  trait UserService {
    def findAll: List[User]
    def save(user: User)
  }
}

而不是:

trait UserService {
  def findAll: List[User]
  def save(user: User)
}

trait UserServiceComponent {
  def userService: UserService
}

第二种方法似乎更具普遍性,因为UserService特征未绑定到特定组件实例。

我遗失了什么?

编辑: 通过"更普遍"我的意思是你可以做这样的事情(将两个不同的蛋糕混合成一个):

object Program extends App with UserServiceComponent with ProductServiceComponent  {
    object Cake1 extends UserServiceComponentImpl with DatabaseComponent1Impl {
    }
    object Cake2 extends ProductServiceComponentImpl with DatabaseComponent2Impl {
    }

    def userService = Cake1.userService
    def productService = Cake2.productService
}

// def
trait DatabaseComponent{
}

trait UserService {
}

trait UserServiceComponent {
  def userService: UserService
}

trait ProductService {
}

trait ProductServiceComponent {
  def productService: ProductService
}

// impl
trait DatabaseComponent1Impl extends DatabaseComponent {
}

trait DatabaseComponent2Impl extends DatabaseComponent {
}

trait UserServiceComponentImpl extends UserServiceComponent {
    self:DatabaseComponent =>

    def userService = new UserService {}
}

trait ProductServiceComponentImpl extends ProductServiceComponent {
    self:DatabaseComponent =>

    def productService = new ProductService {}
}

如果您将UserService定义为嵌套特征,那么您将获得异常: 类型不匹配; found:Program.Cake1.UserService,required:Program.UserService

2 个答案:

答案 0 :(得分:3)

在你的第二个构造中,全局命名空间的数量增加了一倍,没有充分的理由。使用经典的Cake构造,组件是自包含的,它只在全局命名空间中注入一个名称。

在任何一种情况下,组件的特征(此处trait UserService)同样可用,无论结构为经典Cake还是您的替代品。也就是说,你的选择绝不是“更普遍的”。

答案 1 :(得分:1)

兰德尔舒尔茨'答案绝对正确。我只是补充说,有时第二种形式(顶级UserService)是不可避免的。例如,当您必须从"外部"蛋糕到内心"蛋糕:

trait ExampleComponent {
    def example: Example
}

trait Example {
    def doSomething()
}

trait DefaultExampleComponent {
    override val example = new Example {
        // ...
    }
}

trait SomeOtherComponent { self: ExampleComponent =>
    object InnerCake extends ExampleComponent {
        override def example = self.example
    }
}

object TopLevelCake extends DefaultExampleComponent with SomeOtherComponent

如果ExampleExampleComponent的内在特征,那么分配

override def example = self.example

是不可能的,因为self.example的类型为SomeOtherComponent.this.type#Example,但InnerCake.example的类型应为this.type#Example