我目前正在申请使用蛋糕模式。
关于我在网上找到的例子,这些例子是基本的,但不涉及更复杂的需求。我想做的事情并不那么花哨:我想在蛋糕模式应用程序中使用相同类型的2个服务,使用不同的实现。
trait UserServiceComponent {
self: UserRepositoryComponent =>
val userService: UserService
class DefaultUserService extends UserService {
def getPublicProfile(id: String): Either[Error, User] = userRepository.getPublicProfile(id)
}
class AlternativeUserService extends UserService {
def getPublicProfile(id: String): Either[Error, User] = call webservice here for exemple...
}
}
trait UserService extends RepositoryDelegator[User] {
def getPublicProfile(id: String): Either[Error, User]
}
如果我一次使用UserService
的一个实现,它工作正常,但如果我同时需要两个实现,我真的不知道该怎么做。
我应该创建2个不同的组件吗?每一个都暴露出不同的userService值名称? (defaultUserService / alternativeUserService)。使用一个组件进行实现我不知道其他组件在使用名称userService
时如何能够知道使用了哪个实现,因为我的应用程序中有2个不同的实现。
顺便说一句,由于组件表达了对UserRepositoryComponent
的依赖关系,而所有实现都不需要它,我发现只有一个组件正确有点奇怪吗?
想象一下,我不想构建需要两种实现的完整应用程序,但是对于测试来说,我只需要构建不需要UserRepositoryComponent
的AlternativeUserService,否则必须提供这种依赖性是很奇怪的。因为它不会被使用。
有人可以给我一些建议,以便我知道该怎么做吗?
有关的问题: Cake pattern: how to get all objects of type UserService provided by components
由于
答案 0 :(得分:8)
首先,您应该将UserServiceComponent
与UserService
的实施分开:
trait UserService extends RepositoryDelegator[User] {
def getPublicProfile(id: String): Either[Error, User]
}
trait UserServiceComponent {
val userService: UserService
}
trait DefaultUserServiceComponent extends UserServiceComponent { self: UserRepositoryComponent =>
protected class DefaultUserService extends UserService {
def getPublicProfile(id: String): Either[Error, User] = userRepository.getPublicProfile(id)
}
val userService: UserService = new DefaultUserService
}
trait AlternativeUserServiceComponent extends UserServiceComponent {
protected class AlternativeUserService extends UserService {
def getPublicProfile(id: String): Either[Error, User] = call webservice here for exemple...
}
val userService: UserService = new AlternativeUserService
}
如果看起来很冗长,那就好了。蛋糕图案不是特别简洁。
但请注意,即使没有实际需要(例如仅使用UserRepositoryComponent
时),它如何解决关于依赖AlternativeUserService
的问题。
现在,在实例化应用程序时我们要做的就是混合使用DefaultUserServiceComponent
或AlternativeUserServiceComponent
。
如果您碰巧需要访问这两个实现,那么您确实应该公开两个userService值名称。其实,3个名字,如:
DefaultUserService
实施的默认用户服务AlternativeUserService
实施UserService
实现的mainUserService(应用程序在“混合时间”选择哪一个)。以示例:
trait UserService extends RepositoryDelegator[User] {
def getPublicProfile(id: String): Either[Error, User]
}
trait MainUserServiceComponent {
val mainUserService: UserService
}
trait DefaultUserServiceComponent { self: UserRepositoryComponent =>
protected class DefaultUserService extends UserService {
def getPublicProfile(id: String): Either[Error, User] = userRepository.getPublicProfile(id)
}
val defaultUserService: UserService = new DefaultUserService
}
trait AlternativeUserServiceComponent {
protected class AlternativeUserService extends UserService {
def getPublicProfile(id: String): Either[Error, User] = ??? // call webservice here for exemple...
}
val alternativeUserService: UserService = new AlternativeUserService
}
然后你可以像这样实例化你的蛋糕:
object MyApp
extends MainUserServiceComponent
with DefaultUserServiceComponent
with AlternativeUserServiceComponent
with MyUserRepositoryComponent // Replace with your real UserRepositoryComponent here
{
//val userService = defaultUserService
val mainUserService = alternativeUserService
}
在上面的示例中,明确要访问DefaultUserService
的服务会将DefaultUserServiceComponent
作为其组件的依赖(AlternativeUserService
和AlternativeUserServiceComponent
相同),以及只需要某些 UserService
的服务会将MainUserServiceComponent
作为依赖项。您决定“混合时间”服务mainUserService
指向哪个(此处,它指向DefaultUserService
实施。