我第一次尝试使用蛋糕模式。
我有点理解它是如何工作的,但是想知道是否有可能混合已经混合的特性或类似的东西。
我想要的是用蛋糕模式构建一个全局应用程序。 我希望该应用程序的另一个版本是相同的,除了在存储库级别。
是否可以执行以下操作:
trait application extends DefaultUserServiceComponent with MongoUserRepositoryComponent
object realApplication extends application
object fakeApplication extends FakeUserRepositoryComponent with application
我的意思是:在使用假存储库构建虚假应用程序时重用已经构建的应用程序?
答案 0 :(得分:2)
简短回答:不。你会继承冲突的成员。请参阅以下代码段:
trait Repository {def authenticate(username: String, password: String): String}
trait UserServiceComponent {self: UserRepositoryComponent =>
val userService: UserService = new UserService
class UserService {
def authenticate(username: String, password: String): String =
repository.authenticate(username, password)
}
}
trait UserRepositoryComponent {
def repository: Repository
}
trait MongoUserRepositoryComponent extends UserRepositoryComponent {
val repository: Repository =
new Repository {def authenticate(username: String, password: String) = "MongoAuthed"}
}
trait MockUserRepositoryComponent extends UserRepositoryComponent {
val repository: Repository =
new Repository {def authenticate(username: String, password: String) = "MockAuthed"}
}
trait Application extends UserServiceComponent with MongoUserRepositoryComponent
object RealApplication extends Application
// The following will be an error: "object FakeApplication inherits conflicting members:"
object FakeApplication extends Application with MockUserRepositoryComponent
相反,为了获得所需的行为,请将Application定义为:
trait Application extends UserServiceComponent {self: UserRepositoryComponent =>}
object RealApplication extends Application with MongoUserRepositoryComponent
object FakeApplication extends Application with MockUserRepositoryComponent
要保持OP中给出的层次结构,您需要修改代码:
trait MongoUserRepositoryComponent extends UserRepositoryComponent {
private val _repository = new Repository {def authenticate(username: String, password: String) = "MongoAuthed"}
def repository: Repository = _repository
}
trait MockUserRepositoryComponent extends UserRepositoryComponent {
private val _repository = new Repository {def authenticate(username: String, password: String) = "MockAuthed"}
def repository: Repository = _repository
}
trait Application extends UserServiceComponent with MongoUserRepositoryComponent
object RealApplication extends Application
object FakeApplication extends Application with MockUserRepositoryComponent {
override val repository: Repository = super[MockUserRepositoryComponent].repository
}
其他private val _repository
是必需的,以便我们可以将repository
定义为函数,以便它可以在FakeApplication
中用作覆盖。 (使用super[type]
覆盖仅适用于函数)。
编辑:最后,蛋糕模式的目的是开发一个层次结构,其中一个不需要覆盖,就像我提供的最后一个代码片段一样。实际上,特征Application
根本不应存在,只有RealApplication
和FakeApplication
。 (在第二段代码中,我基本上只是将UserServiceComponent
重命名为Application
)。